superponer - ¿Cómo convertir una columna de marco de datos a tipo numérico?
superponer graficas en r (16)
¿Cómo convertir una columna de marco de datos a un tipo numérico?
Algo que me ha ayudado: si tiene rangos de variables para convertir (o solo más de una), puede usar sapply
.
Un poco absurdo pero solo por ejemplo:
data(cars)
cars[, 1:2] <- sapply(cars[, 1:2], as.factor)
Diga que las columnas 3, 6-15 y 37 de su marco de datos se deben convertir a números uno podría:
dat[, c(3,6:15,37)] <- sapply(dat[, c(3,6:15,37)], as.numeric)
Aunque otros han cubierto el tema bastante bien, me gustaría agregar este rápido pensamiento / sugerencia adicional. Podría usar regexp para verificar por adelantado si los caracteres potencialmente consisten solo de números.
for(i in seq_along(names(df)){
potential_numcol[i] <- all(!grepl("[a-zA-Z]",d[,i]))
}
# and now just convert only the numeric ones
d <- sapply(d[,potential_numcol],as.numeric)
Para obtener expresiones regulares más sofisticadas y por qué aprender / experimentar su poder, visite este sitio web realmente agradable: http://regexr.com/
Con el siguiente código, puede convertir todas las columnas del marco de datos en numéricas (X es el marco de datos que queremos convertir sus columnas):
as.data.frame(lapply(X, as.numeric))
y para convertir una matriz entera en numérica, tiene dos formas: O bien:
mode(X) <- "numeric"
o:
X <- apply(X, 2, as.numeric)
Alternativamente, puede usar la función data.matrix
para convertir todo en numérico, aunque tenga en cuenta que los factores podrían no convertirse correctamente, por lo que es más seguro convertir todo a character
primero:
X <- sapply(X, as.character)
X <- data.matrix(X)
Usualmente uso este último si quiero convertir a matriz y numérico simultáneamente
En mi PC (R v.3.2.3), apply
o sapply
dar error. lapply
funciona bien.
dt[,2:4] <- lapply(dt[,2:4], function (x) as.factor(as.numeric(x)))
Hubiera agregado un comentario (no se puede calificar bajo)
Sólo para agregar en user276042 y pangratz
dat$x = as.numeric(as.character(dat$x))
Esto anulará los valores de la columna existente x
Para convertir caracteres a números, hay que convertirlos en factores aplicando
BankFinal1 <- transform(BankLoan, LoanApproval=as.factor(LoanApproval))
BankFinal1 <- transform(BankFinal1, LoanApp=as.factor(LoanApproval))
Tiene que hacer dos columnas con los mismos datos, porque una columna no se puede convertir en numérica. Si haces una conversión da el siguiente error
transform(BankData, LoanApp=as.numeric(LoanApproval))
Warning message: In eval(substitute(list(...)), `_data`, parent.frame()) : NAs introduced by coercion
Por lo tanto, después de hacer dos columnas de los mismos datos se aplican.
BankFinal1 < transform(BankFinal1, LoanApp = as.numeric(LoanApp),
LoanApproval = as.numeric(LoanApproval))
Transformará el carácter a numérico con éxito.
Para convertir una columna de marco de datos a numérico solo tienes que hacer:
factor a numérico: -
data_frame$column <- as.numeric(as.character(data_frame$column))
Si bien su pregunta es estrictamente numérica, hay muchas conversiones que son difíciles de entender cuando se comienza con R. El objetivo es abordar los métodos para ayudar. Esta pregunta es similar a esta pregunta .
La conversión de tipos puede ser una molestia en R porque (1) los factores no se pueden convertir directamente a números, primero se deben convertir a clases de caracteres, (2) las fechas son un caso especial que normalmente se debe tratar por separado y (3) hacer un bucle a través de las columnas del marco de datos puede ser complicado. Afortunadamente, el "tidyverse" ha resuelto la mayoría de los problemas.
Esta solución utiliza mutate_each()
para aplicar una función a todas las columnas en un marco de datos. En este caso, queremos aplicar la función type.convert()
, que convierte las cadenas a números en donde puede. Debido a que R ama los factores (no estoy seguro de por qué) las columnas de caracteres que deben permanecer como personajes se cambian a factor. Para solucionar esto, la función mutate_if()
se usa para detectar columnas que son factores y que cambian de carácter. Por último, quería mostrar cómo se puede usar lubridate para cambiar una marca de tiempo en la clase de caracteres a la fecha y la hora, ya que esto también suele ser un bloque para los principiantes.
library(tidyverse)
library(lubridate)
# Recreate data that needs converted to numeric, date-time, etc
data_df
#> # A tibble: 5 × 9
#> TIMESTAMP SYMBOL EX PRICE SIZE COND BID BIDSIZ OFR
#> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 2012-05-04 09:30:00 BAC T 7.8900 38538 F 7.89 523 7.90
#> 2 2012-05-04 09:30:01 BAC Z 7.8850 288 @ 7.88 61033 7.90
#> 3 2012-05-04 09:30:03 BAC X 7.8900 1000 @ 7.88 1974 7.89
#> 4 2012-05-04 09:30:07 BAC T 7.8900 19052 F 7.88 1058 7.89
#> 5 2012-05-04 09:30:08 BAC Y 7.8900 85053 F 7.88 108101 7.90
# Converting columns to numeric using "tidyverse"
data_df %>%
mutate_all(type.convert) %>%
mutate_if(is.factor, as.character) %>%
mutate(TIMESTAMP = as_datetime(TIMESTAMP, tz = Sys.timezone()))
#> # A tibble: 5 × 9
#> TIMESTAMP SYMBOL EX PRICE SIZE COND BID BIDSIZ OFR
#> <dttm> <chr> <chr> <dbl> <int> <chr> <dbl> <int> <dbl>
#> 1 2012-05-04 09:30:00 BAC T 7.890 38538 F 7.89 523 7.90
#> 2 2012-05-04 09:30:01 BAC Z 7.885 288 @ 7.88 61033 7.90
#> 3 2012-05-04 09:30:03 BAC X 7.890 1000 @ 7.88 1974 7.89
#> 4 2012-05-04 09:30:07 BAC T 7.890 19052 F 7.88 1058 7.89
#> 5 2012-05-04 09:30:08 BAC Y 7.890 85053 F 7.88 108101 7.90
Si el marco de datos tiene varios tipos de columnas, algunos caracteres, algunos numéricos, intente lo siguiente para convertir solo las columnas que contienen valores numéricos a numéricos:
for (i in 1:length(data[1,])){
if(length(as.numeric(data[,i][!is.na(data[,i])])[!is.na(as.numeric(data[,i][!is.na(data[,i])]))])==0){}
else {
data[,i]<-as.numeric(data[,i])
}
}
Si te encuentras con problemas con:
as.numeric(as.character(dat$x))
Echa un vistazo a tus marcas decimales. Si son "," en lugar de "." (por ejemplo, "5,3") lo anterior no funcionará.
Una solución potencial es:
as.numeric(gsub(",", ".", dat$x))
Creo que esto es bastante común en algunos países que no hablan inglés.
Teniendo en cuenta que pueden existir columnas de caracteres, esto se basa en @Abdou en los tipos de columna Obtener que la hoja de Excel responde automáticamente :
makenumcols<-function(df){
df<-as.data.frame(df)
cond <- apply(df, 2, function(x) {
x <- x[!is.na(x)]
all(suppressWarnings(!is.na(as.numeric(x))))
})
numeric_cols <- names(df)[cond]
df[,numeric_cols] <- apply(df[,numeric_cols],2, as.character) # deals with factors
df[,numeric_cols] <- sapply(df[,numeric_cols], as.numeric)
return(df)
}
df<-makenumcols(df)
Tim es correcto, y Shane tiene una omisión. Aquí hay ejemplos adicionales:
R> df <- data.frame(a = as.character(10:15))
R> df <- data.frame(df, num = as.numeric(df$a),
numchr = as.numeric(as.character(df$a)))
R> df
a num numchr
1 10 1 10
2 11 2 11
3 12 3 12
4 13 4 13
5 14 5 14
6 15 6 15
R> summary(df)
a num numchr
10:1 Min. :1.00 Min. :10.0
11:1 1st Qu.:2.25 1st Qu.:11.2
12:1 Median :3.50 Median :12.5
13:1 Mean :3.50 Mean :12.5
14:1 3rd Qu.:4.75 3rd Qu.:13.8
15:1 Max. :6.00 Max. :15.0
R>
Nuestro data.frame
ahora tiene un resumen de la columna de factores (recuentos) y los resúmenes numéricos de as.numeric()
--- que está mal, ya que obtuvo los niveles de los factores numéricos --- y el resumen (correcto) de los as.numeric(as.character())
.
con hablar :: convertir
Para convertir fácilmente varias columnas a diferentes tipos de datos, puede usar hablar::convert
. Sintaxis simple: df %>% convert(num(a))
convierte la columna a de df a numérico.
Ejemplo detallado
Permite convertir todas las columnas de mtcars
a carácter.
df <- mtcars %>% mutate_all(as.character) %>% as_tibble()
> df
# A tibble: 32 x 11
mpg cyl disp hp drat wt qsec vs am gear carb
<chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 21 6 160 110 3.9 2.62 16.46 0 1 4 4
2 21 6 160 110 3.9 2.875 17.02 0 1 4 4
3 22.8 4 108 93 3.85 2.32 18.61 1 1 4 1
Con hablar::convert
:
library(hablar)
# Convert columns to integer, numeric and factor
df %>%
convert(int(cyl, vs),
num(disp:wt),
fct(gear))
resultados en:
# A tibble: 32 x 11
mpg cyl disp hp drat wt qsec vs am gear carb
<chr> <int> <dbl> <dbl> <dbl> <dbl> <chr> <int> <chr> <fct> <chr>
1 21 6 160 110 3.9 2.62 16.46 0 1 4 4
2 21 6 160 110 3.9 2.88 17.02 0 1 4 4
3 22.8 4 108 93 3.85 2.32 18.61 1 1 4 1
4 21.4 6 258 110 3.08 3.22 19.44 1 0 3 1
si x
es el nombre de la columna de dat
del marco de datos, x
es de tipo factor, use:
as.numeric(as.character(dat$x))
type.convert()
universal usando type.convert()
y rapply()
:
convert_types <- function(x) {
stopifnot(is.list(x))
x[] <- rapply(x, utils::type.convert, classes = "character",
how = "replace", as.is = TRUE)
return(x)
}
d <- data.frame(char = letters[1:5],
fake_char = as.character(1:5),
fac = factor(1:5),
char_fac = factor(letters[1:5]),
num = 1:5, stringsAsFactors = FALSE)
sapply(d, class)
#> char fake_char fac char_fac num
#> "character" "character" "factor" "factor" "integer"
sapply(convert_types(d), class)
#> char fake_char fac char_fac num
#> "character" "integer" "factor" "factor" "integer"
Como (todavía) nadie obtuvo la marca de verificación, asumo que tiene algún problema práctico en mente, principalmente porque no ha especificado qué tipo de vector desea convertir a numeric
. Le sugiero que aplique la función de transform
para completar su tarea.
Ahora estoy a punto de demostrar cierta "anomalía de conversión":
# create dummy data.frame
d <- data.frame(char = letters[1:5],
fake_char = as.character(1:5),
fac = factor(1:5),
char_fac = factor(letters[1:5]),
num = 1:5, stringsAsFactors = FALSE)
Echemos un vistazo a los data.frame
> d
char fake_char fac char_fac num
1 a 1 1 a 1
2 b 2 2 b 2
3 c 3 3 c 3
4 d 4 4 d 4
5 e 5 5 e 5
y vamos a correr:
> sapply(d, mode)
char fake_char fac char_fac num
"character" "character" "numeric" "numeric" "numeric"
> sapply(d, class)
char fake_char fac char_fac num
"character" "character" "factor" "factor" "integer"
Ahora probablemente te preguntes "¿Dónde hay una anomalía?" Bueno, me he topado con cosas bastante peculiares en R, y esto no es lo más confuso, pero puede confundirte, especialmente si lees esto antes de meterte en la cama.
Aquí va: las dos primeras columnas son de character
. He llamado deliberadamente 2 nd one fake_char
. Encuentra la similitud de esta variable de character
con una que Dirk creó en su respuesta. En realidad es un vector numerical
convertido a character
. Las columnas 3 y 4 son factor
y la última es "puramente" numeric
.
Si utiliza la función de transform
, puede convertir fake_char
en numeric
, pero no la variable char
sí.
> transform(d, char = as.numeric(char))
char fake_char fac char_fac num
1 NA 1 1 a 1
2 NA 2 2 b 2
3 NA 3 3 c 3
4 NA 4 4 d 4
5 NA 5 5 e 5
Warning message:
In eval(expr, envir, enclos) : NAs introduced by coercion
pero si haces lo mismo en fake_char
y char_fac
, tendrás suerte y no tendrás NA:
> transform(d, fake_char = as.numeric(fake_char),
char_fac = as.numeric(char_fac))
char fake_char fac char_fac num
1 a 1 1 1 1
2 b 2 2 2 2
3 c 3 3 3 3
4 d 4 4 4 4
5 e 5 5 5 5
Si guarda el data.frame
transformado y verifica el mode
y la class
, obtendrá:
> D <- transform(d, fake_char = as.numeric(fake_char),
char_fac = as.numeric(char_fac))
> sapply(D, mode)
char fake_char fac char_fac num
"character" "numeric" "numeric" "numeric" "numeric"
> sapply(D, class)
char fake_char fac char_fac num
"character" "numeric" "factor" "numeric" "integer"
Entonces, la conclusión es: Sí, puede convertir un vector de character
en uno numeric
, pero solo si sus elementos son "convertibles" a numeric
. Si solo hay un elemento de character
en vector, obtendrás un error al intentar convertir ese vector a uno numerical
.
Y solo para probar mi punto:
> err <- c(1, "b", 3, 4, "e")
> mode(err)
[1] "character"
> class(err)
[1] "character"
> char <- as.numeric(err)
Warning message:
NAs introduced by coercion
> char
[1] 1 NA 3 4 NA
Y ahora, solo por diversión (o práctica), intente adivinar la salida de estos comandos:
> fac <- as.factor(err)
> fac
???
> num <- as.numeric(fac)
> num
???
Un cordial saludo a Patrick Burns! =)