【问题标题】:Subset rows in a data frame based on a vector of values基于值向量的数据框中的子集行
【发布时间】:2013-02-20 02:17:12
【问题描述】:

我有两个数据集,它们的大小应该相同,但实际上不同。我需要修剪 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

【问题讨论】:

  • 我认为merge 在这里不合适。我不想合并数据集。
  • 不,我认为merge 完全合适。内连接只会为您提供同时位于 A 和 B 中的行。如果合并添加了任何无关的列,则您可以对结果的列进行子集化。
  • 这让我得到了适当的行数,但同样,我只剩下一个数据集。此外,从某个角度来看,这个数据集比我开始使用的数据集更脏 - 我有一个数据集,其中一些行来自“End”,一些行来自“Beg”,我不知道哪些是哪一个。
  • 您首先担心的是错误的。调用合并对两个原始数据帧没有任何作用。因此,您可以执行类似A &lt;- merge(A,B) 的操作。假设没有重复,获得正确的列并不比merge(A,B)[,colnames(A)] 之类的更难。但是,如果您真的只匹配一列,那么对于您的目的而言,adibender 的解决方案可能更简单。
  • 看,我同意在你的情况下,只有一个索引列,合并不是最简单的选择。但是,如果您花时间使用它,您会发现它很有可能用于此目的。重复的列在其名称后附加了.x 或 .y`,因此您可以知道它们来自哪个原始数据帧。它需要 1-2 行额外的代码,但使用 merge 就可以了。

标签: r subset r-faq


【解决方案1】:

这会给你你想要的:

eg2011cleaned <- eg2011[!eg2011$ID %in% bg2011missingFromBeg, ]

您第二次尝试的错误是因为您忘记了,

一般来说,为方便起见,规范 object[index] 将列子集化为 2d object。如果要对行进行子集化并保留所有列,则必须使用规范 object[index_rows, index_columns],而index_cols 可以留空,默认使用所有列。

但是,您仍然需要包含 , 以表明您想要获取行的子集而不是列的子集。

【讨论】:

  • 是的,这解决了问题。不过,我会等待其他答案,以防万一有人想出一些非常聪明的东西。 :)
  • 如果您将逻辑语句更改为subset(eg2011, !ID %in% bg2011missingFromBeg)subset 将起作用
  • 这真的和我写的答案一样。选择 adibender 的答案,因为它直接解决了您的问题。我只是为其他人添加了我的,以便他们以后偶然发现此页面时可以将其用作更可靠的参考。
  • 对于更快的“data.table”也是如此
【解决方案2】:

如果您真的只想通过两个数据帧中都存在的索引对每个数据帧进行子集化,您可以使用“匹配”函数执行此操作,如下所示:

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

【讨论】:

  • 让我看看能不能用文字重复data_A[data_A$index %in% data_B$index,]。根据它们的索引,给我 data_A 中同时在 data_A 和 data_B 中的所有行。我说的对吗?
  • @Zelbinian 具体来说,它说:给我 data_A 中的所有行,其中 data_A 中的行的索引值可以在 data_B 中的索引值中找到。这是一个稍微不同的说法,但你基本上是正确的。唯一的区别是我们特别想要 data_A 中的行号。如果您颠倒该语句,它将无法正常工作。
  • 不错的可重复示例 + 解释。
【解决方案3】:

真正人类可理解的示例(因为这是我第一次使用 %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

【讨论】:

    【解决方案4】:

    根据原始帖子的 cmets,合并/连接非常适合此问题。特别是,inner join 将只返回两个数据帧中都存在的值,从而不需要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))
    

    为了将数据保存为两个单独的表,每个表只包含自己的变量,这会将不需要的表子集到仅其索引变量,然后再加入。然后没有新的变量被添加到结果表中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-28
      • 1970-01-01
      • 2017-10-08
      相关资源
      最近更新 更多