提问人:Zelbinian 提问时间:3/5/2013 最后编辑:HenrikZelbinian 更新时间:3/24/2021 访问量:185176
基于值向量的数据框中的子集行
Subset rows in a data frame based on a vector of values
问:
我有两个数据集,它们的大小应该相同,但事实并非如此。我需要修剪 A 中不在 B 中的值,反之亦然,以消除进入报表的图形中的噪声。(别担心,这些数据不会被永久删除!
我已阅读以下内容:
但我仍然无法让它正常工作。这是我的代码:
bg2011missingFromBeg <- setdiff(x=eg2011$ID, y=bg2011$ID)
#attempt 1
eg2011cleaned <- subset(eg2011, ID != bg2011missingFromBeg)
#attempt 2
eg2011cleaned <- eg2011[!eg2011$ID %in% bg2011missingFromBeg]
第一次尝试只是消除生成的 setdiff 向量中的第一个值。第二次尝试产生和笨拙的错误:
Error in `[.data.frame`(eg2012, !eg2012$ID %in% bg2012missingFromBeg)
: undefined columns selected
答:
86赞
adibender
3/5/2013
#1
这将为您提供您想要的东西:
eg2011cleaned <- eg2011[!eg2011$ID %in% bg2011missingFromBeg, ]
第二次尝试中的错误是因为你忘记了,
通常,为方便起见,规范将列子集用于 2d .如果要子集行并保留所有列,则必须使用规范,而可以留空,默认情况下将使用所有列。object[index]
object
object[index_rows, index_columns]
index_cols
但是,您仍然需要包含 以指示要获取行的子集而不是列的子集。,
评论
0赞
Zelbinian
3/5/2013
是的,这解决了问题。不过,我会等待其他答案,以防万一有人想出一些非常聪明的东西。:)
1赞
Señor O
3/5/2013
subset
如果将逻辑语句更改为subset(eg2011, !ID %in% bg2011missingFromBeg)
0赞
Dinre
3/5/2013
这和我写的答案真的是一样的。选择adibender的答案,因为它直接解决了你的问题。我只是为其他人添加了我的,以便他们以后偶然发现此页面时能够用作更强大的参考。
0赞
JaKu
2/2/2017
对于更快的“data.table”也是如此
17赞
Dinre
3/5/2013
#2
如果你真的只想通过两个数据框中都存在的索引来子集每个数据框,你可以使用“match”函数来做到这一点,如下所示:
data_A[match(data_B$index, data_A$index, nomatch=0),]
data_B[match(data_A$index, data_B$index, nomatch=0),]
不过,这与以下相同:
data_A[data_A$index %in% data_B$index,]
data_B[data_B$index %in% data_A$index,]
下面是一个演示:
# Set seed for reproducibility.
set.seed(1)
# Create two sample data sets.
data_A <- data.frame(index=sample(1:200, 90, rep=FALSE), value=runif(90))
data_B <- data.frame(index=sample(1:200, 120, rep=FALSE), value=runif(120))
# Subset data of each data frame by the index in the other.
t_A <- data_A[match(data_B$index, data_A$index, nomatch=0),]
t_B <- data_B[match(data_A$index, data_B$index, nomatch=0),]
# Make sure they match.
data.frame(t_A[order(t_A$index),], t_B[order(t_B$index),])[1:20,]
# index value index.1 value.1
# 27 3 0.7155661 3 0.65887761
# 10 12 0.6049333 12 0.14362694
# 88 14 0.7410786 14 0.42021589
# 56 15 0.4525708 15 0.78101754
# 38 18 0.2075451 18 0.70277874
# 24 23 0.4314737 23 0.78218212
# 34 32 0.1734423 32 0.85508236
# 22 38 0.7317925 38 0.56426384
# 84 39 0.3913593 39 0.09485786
# 5 40 0.7789147 40 0.31248966
# 74 43 0.7799849 43 0.10910096
# 71 45 0.2847905 45 0.26787813
# 57 46 0.1751268 46 0.17719454
# 25 48 0.1482116 48 0.99607737
# 81 53 0.6304141 53 0.26721208
# 60 58 0.8645449 58 0.96920881
# 30 59 0.6401010 59 0.67371223
# 75 61 0.8806190 61 0.69882454
# 63 64 0.3287773 64 0.36918946
# 19 70 0.9240745 70 0.11350771
评论
0赞
Zelbinian
3/6/2013
让我看看我能不能用语言重复一遍。根据索引,给我data_A中同时位于 data_A 和 data_B 中的所有行。我说得对吗?data_A[data_A$index %in% data_B$index,]
4赞
Dinre
3/6/2013
@Zelbinian 具体来说,它说:给我data_A中的所有行,其中 data_A 行的索引值可以在 data_B 中的索引值中找到。这是一个略有不同的陈述,但你基本上是正确的。唯一的区别是,我们特别需要 data_A 中的行号。如果反转语句,它将无法正常工作。
0赞
Sam Firke
4/1/2015
很好的可重现示例+解释。
3赞
Sam Firke
4/1/2015
#3
根据对原始帖子的评论,合并/联接非常适合这个问题。具体而言,内部联接将仅返回两个 DataFrame 中都存在的值,因此不需要该语句。setdiff
使用 Dinre 示例中的数据:
在基础 R 中:
cleanedA <- merge(data_A, data_B[, "index"], by = 1, sort = FALSE)
cleanedB <- merge(data_B, data_A[, "index"], by = 1, sort = FALSE)
使用 dplyr 软件包:
library(dplyr)
cleanedA <- inner_join(data_A, data_B %>% select(index))
cleanedB <- inner_join(data_B, data_A %>% select(index))
为了将数据保留为两个单独的表,每个表仅包含自己的变量,这会在联接之前将不需要的表子集仅为其索引变量。然后,不会将新变量添加到生成的表中。
6赞
maycca
4/14/2016
#4
真正人类可以理解的例子(因为这是我第一次使用 %in%),如何比较两个数据帧并在特定列中仅保留包含相等值的行:
# Set seed for reproducibility.
set.seed(1)
# Create two sample data frames.
data_A <- data.frame(id=c(1,2,3), value=c(1,2,3))
data_B <- data.frame(id=c(1,2,3,4), value=c(5,6,7,8))
# compare data frames by specific columns and keep only
# the rows with equal values
data_A[data_A$id %in% data_B$id,] # will keep data in data_A
data_B[data_B$id %in% data_A$id,] # will keep data in data_b
结果:
> data_A[data_A$id %in% data_B$id,]
id value
1 1 1
2 2 2
3 3 3
> data_B[data_B$id %in% data_A$id,]
id value
1 1 5
2 2 6
3 3 7
评论
merge
merge
A <- merge(A,B)
merge(A,B)[,colnames(A)]
.x
merge