select 列根据 R 中另一列的值

select column according to value of another column in R

我正在 R 中处理一个如下所示的数据集(即 w3):

Q1   Q2   Q3   Q4 WorksheetID UserID
395 2178 2699 1494           3     65
395 2178 2694 1394           3     78
395 1178 2699 1394           3     79
395  278 2699 1394           3     80
295 1188 2799 1494           3     81
395 2278 2699 2394           3     81
395 2178 2699 1394           3     83
495 1178 2709 1394           3     84
395 2198 2799 1294           3     85
395 2178 2699 1394           3     85
395 1178 2699 1394           3     86

每个用户都回答了工作表的 4 个问题(Q1、Q2、Q3、Q4)。

我想做的是根据每个问题中回答的答案对用户进行分组。

例如第一季度

Q1   freq UserID
295  1    81
395  9    65 78 79 80 81 83 85 85 86
495  1    84

我所做的是

w3Q1<-count(W3,"Q1")
for(i in w3Q1$Q1)
  {qry<-paste('select userID from w3 where Q1=',i)
  print(i)
  print(sqldf(qry))}

我的问题是,如何将上面的结果结合起来,变成table,变量为Q1、freq、UserID(如上图)?或者有什么更简单的方法吗?

非常感谢

我们可以先用table计算频率,然后强制转换为data.frame。然后我们可以将 pasteUserIDaggregatemerge 这两个数据帧分组:

tbl <- as.data.frame(table(df$Q1))
ids <- aggregate(UserID~Q1, df, paste, collapse=' ')
merge(tbl, ids, by.x='Var1', by.y='Q1')
#   Var1 Freq                     UserID
# 1  295    1                         81
# 2  395    9 65 78 79 80 81 83 85 85 86
# 3  495    1                         84

我们还可以使用 dplyr.

按 'Q1' 和 summarise 分组
library(dplyr)
df1 %>%
   group_by(Q1) %>%
   summarise(freq= n(), UserID= toString(UserID))
#     Q1  freq                             UserID
#   (int) (int)                              (chr)
#1   295     1                                 81
#2   395     9 65, 78, 79, 80, 81, 83, 85, 85, 86
#3   495     1                                 84

对于问题 Q1:Q4,最好将 tidyr 中的 gather 重新整形为长格式。

library(tidyr)
gather(df1, Var, Qs, Q1:Q4) %>% 
        group_by(Var, Qs) %>%
        summarise(freq=n(), UserID = toString(UserID))

正如@Steven Beaupré 提到的,如果我们需要 list,我们可以将 toString 替换为 list(UserID)


使用 data.table 的类似方法是将 'data.frame' 转换为 'data.table' (setDT(df1)),按 'Q1' 分组,我们得到 nrow (.N) 因为 'freq' 和 paste 在一起 'UserID'

library(data.table)
setDT(df1)[, list(freq=.N, UserID=toString(UserID)), by = Q1]

对于多Q列,我们melt格式化为'long',然后分组汇总。

melt(setDT(df1), measure=1:4)[, list(freq=.N, 
      UserID= toString(UserID)) ,.(variable, value)]