Dans R, Comment puis-je calculer des statistiques en pourcentage sur une colonne dans un dataframe? (fonction de tableau étendue avec des pourcentages)

C'est une question simple mais je ne pouvais pas comprendre comment utiliser prop.table pour cela et j'ai besoin de cette fonctionnalité très très souvent.

J'ai des données comme ceci

> 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 savoir pourcentage de fumeurs vs 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 façon de le faire?

(encore mieux ce serait de le faire sur un ensemble de colonnes (que j'énumère) et avoir une sortie un peu bien formatée) (par exemple, le tabagisme, le jour et l' temps)

22
demandé sur userJT 2012-03-08 23:40:59

4 réponses

Si c'est la concision que vous recherchez, vous aimerez peut-être:

prop.table(table(tips$smoker))

Et puis échelle par 100 et rond si vous le souhaitez. Ou plus comme votre sortie exacte:

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

Si vous vouliez le faire pour plusieurs colonnes, il y a beaucoup de directions différentes que vous pourriez aller en fonction de ce que vos goûts vous disent est une sortie propre, 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 les do.call et les laisser dans une liste.

48
répondu joran 2012-03-08 22:17:53

Votre code ne me semble pas si laid...
cependant, une autre (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
9
répondu digEmAll 2012-03-08 20:15:35

Je ne suis pas sûr à 100%, mais je pense que cela fait ce que vous voulez en utilisant prop.table. Voir la plupart du temps 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
répondu Mark Miller 2012-03-08 21:05:27

J'ai fait cela pour en faisant des fonctions d'agrégation et similaires

per.fun <- function(x) {
    if(length(x)>1){
        denom <- length(x);
        num <- sum(x);
        percentage <- num/denom;
        percentage*100
        }
        else NA
    }
0
répondu James Holland 2013-03-06 16:59:31