Applicare la funzione di ciascuna colonna in un frame di dati osservando ogni colonna tipo di dati esistenti

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

  •  25-10-2019
  •  | 
  •  

Domanda

Sto cercando di ottenere il min / max per ogni colonna in una grande cornice di dati, come parte di di conoscere i miei dati . Il mio primo tentativo è stato:

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

Si tratta tutto ciò come un vettore di carattere, perché le prime colonne sono i tipi di carattere. Così max di alcune delle colonne numeriche è venuta fuori come " -99.5".

Poi ho provato questo:

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

ma lamenta di max non significativo per i fattori . (lapply è lo stesso.) Ciò che mi confonde è che il pensiero apply max era perfettamente significativo per i fattori, per esempio è tornato "ZEBRA" per la colonna 1.

A proposito, ho preso uno sguardo al Utilizzando sapply sul vettore di POSIXct e una delle risposte dice " Quando si utilizza sapply, gli oggetti sono costretto a numerico, ... ". E 'questo che mi sta succedendo? Se è così, c'è un'alternativa funzione che non costringere applica? Sicuramente è una necessità comune, come una delle caratteristiche fondamentali del tipo di frame di dati è che ogni colonna può essere di tipo diverso.

È stato utile?

Soluzione

Se si trattasse di un "fattore ordinata" le cose sarebbero diverse. Il che non vuol dire che mi piace "fattori ordinato", non lo faccio, solo per dire che alcuni rapporti sono definiti per 'ordinato' fattori che non sono definiti per i "fattori". Fattori che sono pensati come variabili categoriali ordinarie. Stai visualizzando l'ordine naturale tipo di fattori che è alfabetico ordine lessicale a quelle locali. Se si desidera ottenere una conversione automatica a "numerico" per ogni colonna, ... date e fattori e tutti, quindi provare:

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

O se si vuole testare per i fattori prima di ritorno, ci si aspetta quindi:

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

@Darrens commento funziona meglio:

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

max non riesce con i vettori di caratteri.

Altri suggerimenti

La ragione per cui max funziona con apply è che apply si costringono frame di dati ad una matrice prima, e una matrice può contenere solo un tipo di dati. Così si finisce con una matrice di caratteri. sapply è solo un wrapper per lapply, quindi non è sorprendente che sia resa lo stesso errore.

Il comportamento predefinito quando si crea un frame di dati è per le colonne categoriche per essere memorizzati come fattori . A meno che non si specifica che si tratta di un ordinato fattore, operazioni come max e min sarà indefinito, poiché R è supponendo che hai creato un non ordinato fattore.

È possibile modificare questo comportamento specificando options(stringsAsFactors = FALSE), che cambierà l'impostazione predefinita per l'intera sessione, oppure si può passare stringsAsFactors = FALSE nella costruzione data.frame() chiamare se stesso. Si noti che questo significa semplicemente che min e max assumeranno ordine "alfabetico" per impostazione predefinita.

In alternativa, è possibile specificare manualmente un ordinamento per ogni fattore, anche se dubito che è quello che si vuole fare.

Indipendentemente, sapply generalmente produrrà un vettore atomico, che comporterà la conversione di tutto per caratteri in molti casi. Un modo per aggirare questo è il seguente:

#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

Se si vuole imparare la vostra summary (df) dati fornisce il min, 1 ° quantile, mediana e media, 3 ° quantile e massimo di colonne numeriche e la frequenza dei livelli superiori delle colonne fattore.

sulla base di @ ltamar risposta:
Usa sintesi e munge l'uscita in qualcosa! Utile

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

Non è bello e non è certamente veloce, ma ottiene il lavoro fatto!

Una soluzione utilizzando retype() da hablar a fattori costringere a carattere o tipo numerico seconda fattibilità. Userei dplyr per l'applicazione di massima per ogni colonna.

Codice

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)

Risultato

Non i nuovi tipi di colonna.

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

Dati

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

Il modo migliore in assoluto per farlo è di base evita * applicare funzioni, che converte l'intero frame di dati a matrice, e l'uso colwise da plyr . (Mi sorprende che nessuno ha menzionato questo)

Esempio utilizzando parse_guess come una funzione che opera su tutti i tipi di tipi di dati vettoriali:

colwise(parse_guess)(t)

Meno risposta interessante: si può applicare su ogni colonna con un ciclo for:

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

Non so di un buon modo di fare incarico con * applicare preservando frame di dati struttura .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top