web-dev-qa-db-fra.com

Dans R, comment puis-je calculer des statistiques de pourcentage sur une colonne dans un cadre de données? (fonction de table étendue avec des pourcentages)

C’est une question simple, mais je n’ai pas trouvé comment utiliser prop.table pour cela et j’ai besoin de cette fonctionnalité très souvent.

J'ai des données comme ça

> library(ggplot2)
> #sample data
> head(tips,3)
  total_bill tip    sex smoker day   time size
1         17 1.0 Female     No Sun Dinner    2
2         10 1.7   Male     No Sun Dinner    3
3         21 3.5   Male     No Sun Dinner    3
> #how often there is a non-smoker
> table(tips$smoker)

 No Yes 
151  93 
> #how many subjects
> nrow(tips)
[1] 244

Et j'ai besoin de connaître le pourcentage de fumeurs par rapport aux non-fumeurs Quelque chose comme ceci (code laid):

> #percentage of smokers
> options(digits=2)
> transform(as.data.frame(table(tips$smoker)),percentage_column=Freq/nrow(tips)*100)
  Var1 Freq percentage_column
1   No  151                62
2  Yes   93                38
> 

Y a-t-il une meilleure manière de faire cela?

(Encore mieux, ce serait de le faire sur un ensemble de colonnes (que j’énumère) et d’avoir une sortie assez bien formatée) (par exemple, fumeur, jour et heure)

25
userJT

Si vous recherchez la concision, vous pourriez aimer:

prop.table(table(tips$smoker))

et puis balancez par 100 et arrondissez si vous aimez. Ou plus comme votre sortie exacte:

tbl <- table(tips$smoker)
cbind(tbl,prop.table(tbl))

Si vous voulez faire cela pour plusieurs colonnes, vous pouvez choisir un grand nombre de directions différentes en fonction de ce que vos goûts vous disent être une sortie nette, mais voici une option:

tblFun <- function(x){
    tbl <- table(x)
    res <- cbind(tbl,round(prop.table(tbl)*100,2))
    colnames(res) <- c('Count','Percentage')
    res
}

do.call(rbind,lapply(tips[3:6],tblFun))
       Count Percentage
Female    87      35.66
Male     157      64.34
No       151      61.89
Yes       93      38.11
Fri       19       7.79
Sat       87      35.66
Sun       76      31.15
Thur      62      25.41
Dinner   176      72.13
Lunch     68      27.87

Si vous n'aimez pas empiler les différentes tables les unes sur les autres, vous pouvez abandonner le do.call et les laisser dans une liste.

50
joran

Votre code ne semble pas si moche pour moi ...
cependant, une alternative (pas beaucoup mieux) pourrait être par exemple. :

df <- data.frame(table(yn))
colnames(df) <- c('Smoker','Freq')
df$Perc <- df$Freq / sum(df$Freq) * 100

------------------
  Smoker Freq Perc
1     No   19 47.5
2    Yes   21 52.5
10
digEmAll

Je ne suis pas certain à 100%, mais je pense que cela correspond à ce que vous voulez en utilisant prop.table. Voir principalement les 3 dernières lignes. Le reste du code ne fait que créer de fausses données.

set.seed(1234)

total_bill <- rnorm(50, 25, 3)
tip <- 0.15 * total_bill + rnorm(50, 0, 1)
sex <- rbinom(50, 1, 0.5)
smoker <- rbinom(50, 1, 0.3)
day <- ceiling(runif(50, 0,7))
time <- ceiling(runif(50, 0,3))
size <- 1 + rpois(50, 2)
my.data <- as.data.frame(cbind(total_bill, tip, sex, smoker, day, time, size))
my.data

my.table <- table(my.data$smoker)

my.prop <- prop.table(my.table)

cbind(my.table, my.prop)
4
Mark Miller

Je l'ai fait pour quand faire des fonctions d'agrégation et similaire

per.fun <- function(x) {
    if(length(x)>1){
        denom <- length(x);
        num <- sum(x);
        percentage <- num/denom;
        percentage*100
        }
        else NA
    }
0
James Holland