如果满足所有条件,如何对数据帧进行子集化?

时间:2018-02-14 07:14:07

标签: r dataframe subset

我有两个消息ID,比如197,198。我想为那些从这些ID获取消息的用户分配数据框。我只想要那些包含这两个消息ID的行。

数据框为m

我使用过代码

a = c(197,198)
n = subset(m$userid,m$mid %in% a)

我也试过

n = m[m$mid == 197 & m$mid == 198]

这两个代码都在创建OR输出,而我想要AND输出。

这是样本数据框:

mid userid opened

197 1022    Y
197 1036    N
197 1100    Y
198 1000    Y
198 1022    N
198 1036    Y

我希望输出为包含197年和198年中期用户ID的记录

mid userid opened
197 1022    Y
197 1036    N
198 1022    N
198 1036    Y

3 个答案:

答案 0 :(得分:1)

使用sqldf一个解决方案可以实现:

# data
m <- read.table(text = "mid userid opened
197 1022    Y
197 1036    N
197 1100    Y
198 1000    Y
198 1022    N
198 1036    Y", header = T, stringsAsFactors = F)

library(sqldf)

result <- sqldf("SELECT * FROM m 
                WHERE userid in (SELECT userid FROM m WHERE mid == 197) AND
                userid in (SELECT userid FROM m WHERE mid == 198)")

result 

#     mid userid opened
#   1 197   1022      Y
#   2 197   1036      N
#   3 198   1022      N
#   4 198   1036      Y

答案 1 :(得分:1)

使用重复:

m[duplicated(m$userid) | duplicated(m$userid,fromLast = T), ]

#   mid userid opened
# 1 197   1022      Y
# 2 197   1036      N
# 5 198   1022      N
# 6 198   1036      Y

根据您的真实数据,您可能需要先:m2 <- subset(m,mid %in% a),以确保在应用我的解决方案之前,您的表中只有mid a

答案 2 :(得分:0)

为了完整起见,这里有两个data.table方法。两者都能够处理任意长度的a,即只选择2个mid

加入

library(data.table)
setDT(m)[m[mid %in% a][, uniqueN(mid), by = .(userid)][V1 == uniqueN(a)],
         on = "userid"]
   mid userid opened V1
1: 197   1022      Y  2
2: 198   1022      N  2
3: 197   1036      N  2
4: 198   1036      Y  2

表达式

m[mid %in% a][, uniqueN(mid), by = .(userid)][V1 == uniqueN(a)]
   userid V1
1:   1022  2
2:   1036  2

过滤m,然后按mid计算唯一userid的数量,并返回与userid中所有条目匹配的a。 (可以使用uniqueN(a)而不是length(a),但前者更安全。

按行索引进行子集

有一种替代方法可以返回m的行ID,然后用于子集化:

m[mid %in% a][, .I[uniqueN(mid) == uniqueN(a)], by = .(userid)]
   userid V1
1:   1022  1
2:   1022  5
3:   1036  2
4:   1036  6
m[m[mid %in% a][, .I[uniqueN(mid) == uniqueN(a)], by = .(userid)]$V1]
   mid userid opened
1: 197   1022      Y
2: 198   1022      N
3: 197   1036      N
4: 198   1036      Y