在R中跨列获取频率

3

I have data in a data frame in this format:

  grp1 grp2 grp3 grp4 result
1    0    1    0    0      1
2    1    0    0    0      0
3    0    0    0    1      1
4    0    0    0    1      1
5    1    0    0    0      0
6    0    1    0    0      1
.
.
.

这可以通过以下方式生成:

set.seed(13)

groups <- c("grp1", "grp2", "grp3", "grp4", "result")

# Randomly assign each to group and a result
x <- do.call(rbind, lapply(1:50, function(x) c(sample(c(1,0,0,0), 4), sample(0:1, 1))))
df <- data.frame(x)
colnames(df) <- groups

我的目标是让数据格式化为以下形式:
  group      freq
1  grp1 0.5625000
2  grp2 0.5000000
3  grp3 0.6250000
4  grp4 0.2857143

频率是每个组中结果的百分比。

我目前使用dplyr尝试:

library(dplyr)

df %>% 
  group_by(grp1, grp2, grp3, grp4, result) %>% 
  summarize(n = n()) %>% 
  mutate(freq = n / sum(n)) %>%
  select(-n) %>%
  filter(result == 1)

导致
  grp1 grp2 grp3 grp4 result      freq
1    0    0    0    1      1 0.5625000
2    0    0    1    0      1 0.5000000
3    0    1    0    0      1 0.6250000
4    1    0    0    0      1 0.2857143

请参见reshape2::melttidyr::gather - Gregor Thomas
所以你已经达到了你想要的结果。这里有什么问题吗? - David Arenburg
是的,我不理解这个问题。有没有更少行的代码片段? - Colonel Beauvel
5个回答

6
这里有一个关于 data.table 的尝试。
library(data.table)
melt(setDT(df), "result")[, .(freq = sum(value[result == 1])/sum(value)), by = variable]
#    variable      freq
# 1:     grp1 0.2857143
# 2:     grp2 0.6250000
# 3:     grp3 0.5000000
# 4:     grp4 0.5625000

4
“频率是每个组具有结果的百分比”是指每个组等于结果的行的百分比。”
df %>% 
    tidyr::gather(key = group, value = group_choice, grp1:grp4) %>%
    group_by(group) %>%
    filter(group_choice == 1) %>%
    summarize(freq = mean(group_choice == result))

# Source: local data frame [4 x 2]
# 
#   group      freq
# 1  grp1 0.2857143
# 2  grp2 0.6250000
# 3  grp3 0.5000000
# 4  grp4 0.5625000

我所指的频率是:sum(df$grp4 == 1 & df$result == 1) / sum(df$grp4)。你在回答中给出的分组结果是我正在寻找的格式。不过我认为我可以从你的答案中弄清楚它。 - Stoof
编辑完成。现在我的频率匹配了,但是似乎分组是颠倒的?对于排序问题不太确定。 - Gregor Thomas
谢谢,我相信是我的频率反了。这是一个不错而简洁的解决方法来解决我的问题。 - Stoof

3
你也可以使用apply
> freq=apply(df,2,function(x){sum(x==1 & df$result==1)/sum(x)})
> data.frame(freq)
#             freq
# grp1   0.2857143
# grp2   0.6250000
# grp3   0.5000000
# grp4   0.5625000
# result 1.0000000

正如@akrun所建议的那样,你也可以这样做:

summarise_each(df,funs( sum(.==1 & df$result==1)/sum(.))) %>% t()

在这种情况下,apply 似乎提供了最快的解决方案。
akrun=function(df)    {summarise_each(df,funs( sum(.==1 & df$result==1)/sum(.))) %>% t()}
user7598=function(df) {apply(df,2,function(x){sum(x==1 & df$result==1)/sum(x)})}
David=function(df)    {melt(setDT(df), "result")[, .(freq = sum(value[result == 1])/sum(value)), by = variable]}
Gregor=function(df)   {df %>% tidyr::gather(key = group, value = group_choice, grp1:grp4) %>% group_by(group) %>% filter(group_choice == 1) %>% summarize(freq = mean(group_choice == result))}

# SPEED TESTS
set.seed(5)
microbenchmark(akrun(df), Gregor(df),user7598(df),David(df))
Unit: microseconds
         expr       min         lq       mean    median         uq       max neval cld
    akrun(df)  9645.860 10509.3940 12690.5538 10848.248 12315.4020 98239.948   100   c
   Gregor(df) 10319.888 11405.6060 12512.9027 11685.120 12237.1120 26211.999   100   c
 user7598(df)   423.662   491.7045   630.8143   563.958   629.8315  2027.243   100   a  
    David(df)  2115.610  2273.5525  2622.7699  2348.005  2475.2295 15491.534   100   b 

注意:根据@Gregor回答中OP的评论进行更改。


你也可以使用 summarise_each(df,funs( sum(.==1 & df$result==1)/sum(.))) %>% t() - akrun

0

如果我理解正确,您想知道每个组中“1”的百分比,条件是“Result”为1。如果是这样,那么您可以使用apply()函数对列求和,然后除以列的长度。您可以通过在数据框中指定“Result”必须等于1来应用约束。

请注意,在下面的数据框规范中,我告诉R仅针对前四列使用apply,因为“Result”列不需要作为频率计算的一部分。

即:df[条件语句,c(1:4)]

result <- data.frame(apply(df[df$result == 1, c(1:4)], 2,sum)/apply(df[df$result==1, c(1:4) ], 2, length))
colnames(result)<- c("freq")

这将以以下格式生成结果

      freq
grp1 0.1818182
grp2 0.1818182
grp3 0.3636364
grp4 0.2727273

这并没有产生期望的结果。 - User7598

0

我认为colSums()在这里是合适的:

rci <- which(names(df)=='result');
data.frame(group=names(df[-rci]),freq=unname(colSums(df[-rci]==1&df[,rci]==1)/colSums(df[-rci])));
##   group      freq
## 1  grp1 0.2857143
## 2  grp2 0.6250000
## 3  grp3 0.5000000
## 4  grp4 0.5625000

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接