在特定条件下从数据框中提取行
Posted
技术标签:
【中文标题】在特定条件下从数据框中提取行【英文标题】:Extract rows from a data frame under certain conditions 【发布时间】:2019-06-11 13:30:33 【问题描述】:我必须根据特定条件过滤我的数据框。 如果解决方案考虑使用 dplyr 会更好。
我有这样的数据框结构
sentId. B. label. partner. code
1. 2. 3. 4. 123
1. 2. 2. 4. 124
4. 2. 3. 8. 125
7. 3. 2. 7. 126
如果列 label 包含特定值(例如,3.),则不仅要收集该 Row,还要收集具有相同 的所有 Rows sentID 和前一个的合作伙伴价值。
预期的结果是这样的:
sentId. B. label. partner. code
1. 2. 3. 4. 123
1. 2. 2. 4. 124
4. 2. 3. 8. 125
【问题讨论】:
【参考方案1】:我们可以使用%in%
到filter
'sentId.` 和 'partner.' 分组后的行。
library(dplyr)
df1 %>%
group_by(sentId., partner.) %>%
filter(3 %in% label.)
# A tibble: 3 x 5
# Groups: sentId. [2]
# sentId. B. label. partner. code
# <dbl> <dbl> <dbl> <dbl> <int>
#1 1 2 3 4 123
#2 1 2 2 4 124
#3 4 2 3 8 125
或者以简洁的方式使用data.table
library(data.table)
setDT(df1)[, .SD[3 %in% label.], .(sentId., partner.)]
或base R
df1[with(df1, ave(label.==3, sentId., partner., FUN = any)),]
数据
df1 <- structure(list(sentId. = c(1, 1, 4, 7), B. = c(2, 2, 2, 3), label. = c(3,
2, 3, 2), partner. = c(4, 4, 8, 7), code = 123:126),
class = "data.frame", row.names = c(NA,
-4L))
【讨论】:
有必要将 groupBy 也扩展到“partner”值。它以这种方式工作。谢谢 @Silvia 我也加了partner
【参考方案2】:
我们可以首先找出我们感兴趣的label
值所在的行索引,然后使用这些索引从整个数据帧中对sentId
和partner
值进行子集化。
label_value <- 3
inds <- df$label == label_value
df[with(df, sentId %in% sentId[inds] & partner %in% partner[inds]), ]
# sentId B label partner code
#1 1 2 3 4 123
#2 1 2 2 4 124
#3 4 2 3 8 125
dplyr
中的相同逻辑将是
library(dplyr)
df %>%
filter(sentId %in% sentId[label == label_value] &
partner %in% partner[label == label_value])
【讨论】:
【参考方案3】:这个问题可以很容易地用 SQL 来表述,所以一种选择是使用 sqldf
库:
library(sqldf)
# your data frame df
sql <- "SELECT t1.\"sentId.\", t1.\"B.\", t1.\"label.\", t1.\"partner.\", t1.code
FROM yourTable t1
WHERE t1.\"label.\" = '3.' OR
EXISTS (SELECT 1 FROM yourTable t2
WHERE t1.\"sentId.\" = t2.\"sentId.\" AND
t1.\"partner.\" = t2.\"partner.\" AND
t2.\"label.\" = '3.')"
result <- sqldf(sql)
Demo
注意:上面的演示实际上使用了 MariaDB,因为 SQLite 没有使用演示工具。但它仍然表明查询逻辑是正确的。
【讨论】:
【参考方案4】:使用sqldf
:
它将标签为 3 的 sentID
和 partner
提取为两个内部查询,并从中获取结果。
names(df) <- gsub("\\.", "", names(df)) # to remove . from column name
sqldf("select * from df where (sentID IN (select sentID from df where label IS 3) OR
partner IN (select partner from df where label IS 3))")
输出:
sentId B label partner code
1 1 2 3 4 123
2 1 2 2 4 124
3 4 2 3 8 125
【讨论】:
注意:实际的列名中包含点,因此您必须使用底层数据库引擎的特定语法对它们进行转义。 @TimBiegeleisen:感谢您的纠正。从列名中删除第一个.
以使其更容易。以上是关于在特定条件下从数据框中提取行的主要内容,如果未能解决你的问题,请参考以下文章
Meteor / MongoDB - 如何证明数组中的任何项目是不是等于特定值,而不是在“真”的情况下从另一个数组中提取项目?