J'essaie d'obtenir le min/max pour chaque colonne d'un grand bloc de données, dans le cadre de pour connaître mes données . Mon premier essai a été:
apply(t,2,max,na.rm=1)
Il traite tout comme un vecteur de caractères, car les premières colonnes sont des types de caractères. Donc max de certaines des colonnes numériques sort comme " -99.5"
.
J'ai alors essayé ceci:
sapply(t,max,na.rm=1)
mais il se plaint de max non significatif pour les facteurs . (lapply
est identique.) Ce qui me trouble, c'est que apply
pensait max
était parfaitement significatif pour les facteurs, par exemple. il a renvoyé "ZEBRA" pour la colonne 1.
BTW, j'ai jeté un coup d'oeil à tilisation de sapply sur le vecteur de POSIXct et l'une des réponses dit " Lorsque vous utilisez sapply, vos objets sont forcés à être numériques, .. . ". Est-ce ce qui m'arrive? Si tel est le cas, existe-t-il une fonction d'application alternative qui ne contraint pas? C’est sûrement un besoin commun, car l’une des caractéristiques clés du type de trame de données est que chaque colonne peut être d’un type différent.
Si c'était un "facteur ordonné", les choses seraient différentes. Ce qui ne veut pas dire que j'aime les "facteurs ordonnés", mais que certaines relations sont définies pour des "facteurs ordonnés" qui ne sont pas définis pour des "facteurs". Les facteurs sont considérés comme des variables catégoriques ordinaires. Vous voyez l'ordre de tri naturel des facteurs, qui correspond à l'ordre lexical alphabétique de votre région. Si vous voulez obtenir une contrainte automatique sur "numérique" pour chaque colonne, ... dates et facteurs et tout, essayez alors:
sapply(df, function(x) max(as.numeric(x)) ) # not generally a useful result
Ou si vous souhaitez d'abord tester les facteurs et revenir comme prévu, alors:
sapply( df, function(x) if("factor" %in% class(x) ) {
max(as.numeric(as.character(x)))
} else { max(x) } )
Le commentaire de @Darrens fonctionne mieux:
sapply(df, function(x) max(as.character(x)) )
max
réussit avec les vecteurs de caractères.
La raison pour laquelle max
fonctionne avec apply
est que apply
contraint d'abord votre trame de données à une matrice et qu'une matrice ne peut contenir qu'un seul type de données. Donc, vous vous retrouvez avec une matrice de caractères. sapply
n'est qu'un wrapper pour lapply
, il n'est donc pas surprenant que les deux produisent la même erreur.
Le comportement par défaut lorsque vous créez un cadre de données concerne les colonnes catégorielles à stocker sous la forme facteurs. Sauf si vous spécifiez qu'il s'agit d'un facteur ordonné, les opérations telles que max
et min
seront indéfinies, car R suppose que vous avez créé un non ordonné facteur.
Vous pouvez modifier ce comportement en spécifiant options(stringsAsFactors = FALSE)
, qui modifiera la valeur par défaut pour toute la session, ou vous pouvez passer stringsAsFactors = FALSE
Dans l'appel de construction data.frame()
lui-même. Notez que cela signifie simplement que min
et max
assumeront un ordre "alphabétique" par défaut.
Ou vous pouvez spécifier manuellement un ordre pour chaque facteur, bien que je doute que ce soit ce que vous souhaitiez faire.
Quoi qu'il en soit, sapply
donnera généralement un vecteur atomique, ce qui impliquera de tout convertir en caractères dans de nombreux cas. Une solution est la suivante:
#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 vous voulez apprendre vos données, summary (df)
fournit les colonnes min, 1er quantile, médian et moyen, 3e quantile et max des colonnes numériques ainsi que la fréquence des niveaux supérieurs des colonnes de facteurs.
en s'appuyant sur la réponse de @ ltamar:
Utilisez le résumé et convertissez le résultat en quelque chose d’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
Ce n'est pas joli et ce n'est certainement pas rapide mais ça fait le travail!
Une solution utilisant retype()
de hablar pour contraindre des facteurs à un caractère ou à un type numérique, en fonction de la faisabilité. J'utiliserais dplyr
pour appliquer max à chaque colonne.
Code
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)
Résultat
Pas les nouveaux types de colonne.
v1 v2 v3 v4
<dbl> <chr> <dbl> <chr>
1 0.974 j 1.09 J
Données
# Sample data borrowed from @joran
d <- data.frame(v1 = runif(10), v2 = letters[1:10],
v3 = rnorm(10), v4 = LETTERS[1:10],stringsAsFactors = TRUE)
Le meilleur moyen absolu de le faire est d’éviter les fonctions de base * apply, ce qui contraint l’ensemble du cadre de données à un tableau, et d’utiliser colwise
de plyr . (Je suis surpris que personne n'en ait parlé)
Exemple utilisant parse_guess
en tant que fonction opérant sur tous types de types de données vectoriels:
colwise(parse_guess)(t)
Réponse moins intéressante: on peut appliquer sur chaque colonne une boucle for:
for (i in 1:nrow(t)) { t[, i] <- parse_guess(t[, i]) }
Je ne connais pas de bonne façon de faire une assignation avec * appliquer tout en préservant la structure de trame de données .