Aplicar la función a cada columna en un marco de datos de observación de cada una de las columnas de tipo de datos

StackOverflow https://stackoverflow.com/questions/7303322

  •  25-10-2019
  •  | 
  •  

Pregunta

Estoy tratando de conseguir el min/max para cada columna en un gran marco de datos, como parte de conocer a mis datos.Mi primer intento fue:

apply(t,2,max,na.rm=1)

Que todo lo trata como un carácter vectorial, debido a que el primer par de columnas son los tipos de caracteres.Así que max de algunas de las columnas numéricas está saliendo como " -99.5".

Luego traté de esto:

sapply(t,max,na.rm=1)

pero se queja de max no son significativos para los factores de. (lapply es la misma). Lo que me confunde es que apply pensamiento max era perfectamente significativas para los factores, por ejemplo,volvió "CEBRA" para la columna 1.

Por CIERTO, eché un vistazo a El uso de sapply en el vector de POSIXct y una de las respuestas dice "Cuando se utiliza sapply, sus objetos son coaccionados para numérica,...".Esto es lo que me está pasando?Si es así, ¿hay una alternativa de aplicar la función que no coaccionar?Sin duda es una necesidad común, como una de las principales características de la estructura de datos tipo es que cada columna puede ser de un tipo diferente.

¿Fue útil?

Solución

Si se tratara de un "ordenado factor" las cosas serían diferentes.Lo cual no quiere decir que me gusta "ordenó factores", yo no, sólo decir que algunas relaciones se definen por " ordenado factores que no son definidos por los "factores".Se cree que los factores de corrientes variables categóricas.Usted está viendo el natural orden de los factores, que es alfabético léxica orden para su localización.Si usted desea conseguir un sistema automático de " coerción "numérico" para cada columna, ...las fechas y los factores y, a continuación, intente:

sapply(df, function(x) max(as.numeric(x)) )   # not generally a useful result

O si desea probar para los factores de primer y el rendimiento que usted espera entonces:

sapply( df, function(x) if("factor" %in% class(x) ) { 
            max(as.numeric(as.character(x)))
            } else { max(x) } )

@Darrens comentario funciona mejor:

 sapply(df, function(x) max(as.character(x)) )  

max tiene éxito con carácter de vectores.

Otros consejos

La razón que max funciona con apply es eso apply está coaccionando su marco de datos primero a una matriz, y una matriz solo puede contener un tipo de datos. Entonces terminas con una matriz de personajes. sapply es solo un envoltorio para lapply, por lo que no es sorprendente que ambos produzcan el mismo error.

El comportamiento predeterminado cuando crea un marco de datos es que las columnas categóricas se almacenen como factores. A menos que especifique que es un ordenado factor, operaciones como max y min estará indefinido, ya que R supone que ha creado un desordenado factor.

Puedes cambiar este comportamiento especificando options(stringsAsFactors = FALSE), que cambiará el valor predeterminado para toda la sesión, o puede aprobar stringsAsFactors = FALSE en el data.frame() La construcción se llama en sí. Tenga en cuenta que esto solo significa que min y max asumirá el orden "alfabético" por defecto.

O puede especificar manualmente un pedido para cada factor, aunque dudo que eso es lo que quiere hacer.

Sin importar, sapply Generalmente producirá un vector atómico, que implicará convertir todo a los caracteres en muchos casos. Una forma en que esto es la siguiente:

#Some test data
d <- data.frame(v1 = runif(10), v2 = letters[1:10], 
                v3 = rnorm(10), v4 = LETTERS[1:10],stringsAsFactors = TRUE)

d[4,] <- NA

#Similar function to DWin's answer          
fun <- function(x){
    if(is.numeric(x)){max(x,na.rm = 1)}
    else{max(as.character(x),na.rm=1)}
}   

#Use colwise from plyr package
colwise(fun)(d)
         v1 v2       v3 v4
1 0.8478983  j 1.999435  J

Si quieres aprender tus datos summary (df) Proporciona el minuto, 1er cuantil, mediano y media, 3er cuantil y máximo de columnas numéricas y la frecuencia de los niveles superiores de las columnas de factor.

Construyendo en la respuesta de @Ltamar:
¡Use resumen y munde la salida en algo útil!

library(tidyr)
library(dplyr)

df %>% 
  summary %>% 
  data.frame %>%
  select(-Var1) %>%
  separate(data=.,col=Freq,into = c('metric','value'),sep = ':') %>%
  rename(column_name=Var2) %>%
  mutate(value=as.numeric(value),
         metric = trimws(metric,'both') 
  ) %>%  
  filter(!is.na(value)) -> metrics

No es bonito y ciertamente no es rápido, ¡pero hace el trabajo!

Una solución usando retype() Desde el hablar hasta los factores de coacección, el carácter o el tipo numérico dependiendo de la fábrica. Yo usaría dplyr para aplicar máximo a cada columna.

Código

library(dplyr)
library(hablar)

# Retype() simplifies each columns type, e.g. always removes factors
d <- d %>% retype()

# Check max for each column
d %>% summarise_all(max)

Resultado

No los nuevos tipos de columnas.

     v1 v2       v3 v4   
  <dbl> <chr> <dbl> <chr>
1 0.974 j      1.09 J   

Datos

# Sample data borrowed from @joran
d <- data.frame(v1 = runif(10), v2 = letters[1:10], 
                v3 = rnorm(10), v4 = LETTERS[1:10],stringsAsFactors = TRUE)

La mejor manera absoluta de hacerlo es evitar las funciones de la base *Aplicar, que coaccionan todo el marco de datos a la matriz y use colwise de plyr. (Me sorprende que nadie haya mencionado esto)

Ejemplo usando parse_guess Como función que funciona en todo tipo de tipos de datos vectoriales:

colwise(parse_guess)(t)

Respuesta menos interesante: podemos aplicar en cada columna con un bucle for-bucle:

for (i in 1:nrow(t)) { t[, i] <- parse_guess(t[, i]) }

No sé de una buena forma de hacer asignación con *aplicar mientras preserva la estructura del marco de datos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top