以优雅的方式将百分比(每行)列添加到 R 数据帧



我想将百分比值作为data.frame中的一列。示例代码有效。但问题是这是否是正确优雅的R-way

> df <- data.frame(addmargins(table(mtcars$gear, useNA="always")))
> df
Var1 Freq
1    3   15
2    4   12
3    5    5
4 <NA>    0
5  Sum   32
> df$percent <- mapply(function(x) {100 / length(mtcars$gear) * x}, df$Freq)
> df
Var1 Freq percent
1    3   15  46.875
2    4   12  37.500
3    5    5  15.625
4 <NA>    0   0.000
5  Sum   32 100.000

对我来说,没有必要将这个问题限制在data.frame.

我认为添加边距是一种不好的做法,因为您将数据与摘要混合在一起。

df <- data.frame(table(mtcars$gear, useNA="always"))
df$pct <-df$Freq/sum(df$Freq)*100
df
#>   Var1 Freq    pct
#> 1    3   15 46.875
#> 2    4   12 37.500
#> 3    5    5 15.625
#> 4 <NA>    0  0.000

或者在惯用的dplyr代码中(无需打扰table(:

library(dplyr)
mtcars %>%
group_by(gear) %>% 
summarise(Freq=n()) %>% 
mutate(percent=Freq/sum(Freq)*100)
#> # A tibble: 3 x 3
#>    gear  Freq percent
#>   <dbl> <int>   <dbl>
#> 1     3    15    46.9
#> 2     4    12    37.5
#> 3     5     5    15.6

请注意,汇总后无需ungroup,因为您只有一个分组变量,而汇总恰好剥离了一层分组

为了清楚起见,我提倡一个基于dplyr::mutate的解决方案:

df <- df %>%
mutate(percent = (Freq/nrow(mtcars)) * 100)

我想我会在基本 R中使用table函数来完成此任务(从一开始就使用它(:

df <- data.frame(
"g" = names(table(mtcars$gear)), 
"f" = as.numeric(table(mtcars$gear)), 
"p" = as.numeric(100 * (table(mtcars$gear)/length(mtcars$gear)))
)

结果如下:

> df
g  f      p
1 3 15 46.875
2 4 12 37.500
3 5  5 15.625

或者,在创建 data.frame 后添加百分比以获得较短的代码段:

df <- data.frame(table(mtcars$gear))
df$p <- 100 * (df[,'Freq'] / sum(df[,'Freq']))

给:

> df
Var1 Freq      p
1    3   15 46.875
2    4   12 37.500
3    5    5 15.625

1( prop.tableprop.table在这里很有用。 我们使用ave将其分别应用于数据和摘要行。

transform(df, Percent = 100 * ave(Freq, Var1 == "Sum", FUN = prop.table))

给:

Var1 Freq Percent
1    3   15  46.875
2    4   12  37.500
3    5    5  15.625
4 <NA>    0   0.000
5  Sum   32 100.000

2(表格包 如果这样做的目的是显示指示的表格,那么表格包很好。 公式的 LHS 上的项是指行,RHS 上的项是指列。

library(tables)
gear <- factor(mtcars$gear)
tab <- tabular(gear + 1 ~ (n=1) + Percent())

给:

> tab
gear n  Percent
3    15  46.88 
4    12  37.50 
5     5  15.62 
All  32 100.00 

HTML和LaTeX输出现在可以使用html(tab)latex(tab)生成。

这种方法更适合显示,但如果你真的想提取数据,可以这样做:

m <- as.matrix(tab, format = as.numeric)
dimnames(m) <- list(attr(tab, "rowLabels"), attr(tab, "colLabels"))

最新更新