【问题标题】:Condition for subsetting data in R using %in%使用 %in% 对 R 中的数据进行子集化的条件
【发布时间】:2015-03-31 11:24:00
【问题描述】:

我正在使用 subset() 进行一些子集化,但在将 %in% 命令用于我的逻辑语句时遇到了一些问题。

考虑一个简单的数据结构,例如

  x11  x21 x12  x22
1  19 2000  32 2004
2  19 2000  20 2001

我想要一个子集,其中x12 等于x22-x21+x11 或等于x22-x21+x11+1。* 对于上面的示例,我想要第二行,因为逻辑语句应该计算为@987654327 @ 当且仅当 x12 是 20 或 21,这是满足的。对于这个简单的设置,以下对我有用:

> test1 <- data.frame(x11=c(19, 19), x21=c(2000, 2000), x12=c(32, 20), x22=c(2004, 2001))
> subset(test1, (x12 %in% c(x22-x21+x11, x22-x21+x11+1)))
  x11  x21 x12  x22
2  19 2000  20 2001

当我引入额外的行时,问题就出现了。只添加一行:

  x11  x21 x12  x22
1  19 2000  32 2004
2  19 2000  20 2001
3  30 1998  32 2000

现在,我想对其进行子集化,以便获得第二行和第三行。但是使用与上面相同的子集策略:

> test2 <- data.frame(x11=c(19, 19, 30), x21=c(2000, 2000, 1998), x12=c(32, 20, 32), x22=c(2004, 2001, 2000))
> subset(test2, (x12 %in% c(x22-x21+x11, x22-x21+x11+1)))
  x11  x21 x12  x22
1  19 2000  32 2004
2  19 2000  20 2001
3  30 1998  32 2000

所以现在我得到了我在第一个示例中没有得到的行。我的猜测是它与x12 被允许在其中的向量有关,即c(x22-x21+x11, x22-x21+x11+1),但我不确定如何构造它,以便暗示它是“按行”而不是一个所有行的向量。

非常感谢您的想法!


*x11 是个人在时间点 x21 的年龄,x12 是一个(可能不同的)个人在时间点 x22 的年龄。我想要包含 x21 处的年龄 (x11) 在逻辑和物理上与 x22 处的年龄 (x12) 兼容的行的子集; 2000 年 19 岁的人在 2001 年是 19 岁、20 岁还是 21 岁,具体取决于生日(但出于其他原因,我在这里放弃了个人同龄的可能性)。因此,第一行中,我们在 2000 年有 19 岁,在 2004 年有 32 岁,对于同一个人来说是不可能的。

【问题讨论】:

  • which the age difference is possible - 你的意思是检查x12 是否在 x22-x21+x11 和x22-x21+x11+1 之间?
  • @zx8754 好像我把句子的某些部分放在那里了,我已经编辑了我的帖子,让它更有意义(我希望)。

标签: r dataframe subset


【解决方案1】:

首先,请注意浮点精度限制。如果您的值都是整数,这无关紧要,但在一般情况下,x==y 可能会失败,除非您使用像 all.equal 这样的工具。
现在,与其与subset 或%in% 混为一谈,不如写一个条件:

foo <- test1[(test1[,3]==(test1[,1]-test1[,2]+test1[,4])) |
               (test1[,3]==(test1[,1]-test1[,2]+test1[,4]+1)), ]

您可能需要逐行运行apply。

【讨论】:

  • 这似乎做得很好,但你知道(不由自主地)将它用于大型矩阵是否可取?或者给定这样的用途,我应该以某种方式改变它吗?
  • 我怀疑使用&lt;-[ 运算符是更快的方法。您可能想进行一些计时赛。
  • 我在我的代码中使用了这个,但你的答案中有一些错误(缺少括号和加号而不是减号)。为了将来参考,它应该是foo &lt;- test1[(test1[,3]==(test1[,1]-test1[,2]+test1[,4])) | (test1[,3]==(test1[,1]-test1[,2]+test1[,4]+1)), ]。
【解决方案2】:

试试这个:

#data
test2 <- data.frame(x11=c(19, 19, 30),
                    x21=c(2000, 2000, 1998),
                    x12=c(32, 20, 32),
                    x22=c(2004, 2001, 2000))
#range pre-computed
test2$in1 <- test2$x22-test2$x21+test2$x11
test2$in2 <- test2$x22-test2$x21+test2$x11+1

#subset
test2[ test2$x12 >= test2$in1 &
         test2$x12 <= test2$in2,]
#   x11  x21 x12  x22 in1 in2
# 2  19 2000  20 2001  20  21
# 3  30 1998  32 2000  32  33

【讨论】:

  • 这似乎也很有效,但我会问我上面问 Carl Witthoft 的问题:将它用于大型矩阵是否不明智,或者我应该以某种方式改变它?
  • 与我的解决方案基本相同——伟大的思想等 :-)
  • @CarlWitthoft 如果需要,我将合并到您的答案中,我只是无法使您的代码正常工作,而且您正在使用 | 运算符。另外,那 1 票来自我 :)
  • 不,保留你的答案,尤其是我的答案未经证实。我想我在你使用 AND 的地方使用了 OR,但是关系(> vs == 等)不同以匹配。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 2021-02-16
  • 2014-02-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多