【问题标题】:Return duplicates in a list based on 2 criteria根据 2 个条件返回列表中的重复项
【发布时间】:2015-05-22 20:15:53
【问题描述】:

我有一个包含 2 个数据集的列表。

a = data.frame(c(1,1,1,1,1,2,2,2,2,2), c("a","b", "c", "d","e","e","f", "g", "h","i"))
colnames(a) = c("Numbers","Letters")
c = data.frame(c(3,3,3,3,3,4,4,4,4,4), c("q","r", "s", "t","u","u","v", "w", "x","y"))
colnames(c) = c("Numbers","Letters")
my.list = list(a,c)
my.list

我有兴趣只返回在每个数据集的唯一编号之间找到的共同字母。期望的结果如下所示:

new_a = data.frame(c(1,2),c("e","e"))
new_c = data.frame(c(3,4),c("u","u"))
colnames(new_a) = c("Numbers","Letters")
colnames(new_c) = c("Numbers","Letters")
my.new.list = list(new_a,new_c)
my.new.list

如您所见,字母“e”是数据集 1 中数字“1”和“2”共享的唯一常见字母,而字母“u”是数据集中数字 3 和 4 共享的唯一常见字母2.

我正在尝试为一个非常大的列表执行此操作。为了让您了解我的真正问题,我有一个列表,其中每个元素都是一个状态。在每个州,我都有多个资产经理或“账户”,每个账户都有多个代码。我正在尝试查找每个地理位置的帐户共有的代码。在上面的例子中,数字是账户,字母是股票代码,列表中包含的两个数据集是两个不同的状态。我希望这有助于解决我的问题。

谢谢!

【问题讨论】:

  • c 是一个非常常用的函数,因此您可能不想将其用作其他名称。
  • 我对您的描述有疑问。假设如果数据集被扩展为包含更多类别的“数字”,即a1 <- rbind(a, a[1:5,]); a1$Numbers[11:15] <- 3; a1$Letters[15] <- 'f',基于新数据集a1的预期结果是什么@

标签: r list duplicates subset


【解决方案1】:
library(data.table)
a <- as.data.table(a)
a[, if(.N > 1) .SD, by = list(Letters)]
#    Letters Numbers
# 1:       e       1
# 2:       e       2

说明:取表a并按列Lettersby = list(Letters))分组,仅当行数(.N)为那个组是>1。

【讨论】:

  • 根据 OP 的措辞,这在某些情况下会失败。另外,这不考虑my.list
  • 方括号有一些开销,所以我会使用if (.N&gt;1) .SD 而不是.SD[.N&gt;1]
  • 我猜 OP 知道如何将其扩展到列表,但它是:lapply(my.list,function(x)as.data.table(x)[,if(.N&gt;1).SD,by=Letters])
  • @Frank 这不是唯一的问题。 OP只想要公共元素,这是否还包括所有数字中不常见的元素,比如是否有更多类别的数字
  • @akrun 也许您可以添加一个小示例来说明您的答案如何涵盖您正在谈论的案例?我并没有真正遵循;这个答案符合我对问题的阅读。
【解决方案2】:

我们可以在base R 中使用Reduceintersect

 lapply(my.list, function(x) x[with(x, Letters %in%
                 Reduce(intersect, split(Letters, Numbers))),])

或使用dplyr

 library(dplyr)
 lapply(my.list, function(x)
                    x %>% 
                        group_by(Letters) %>% 
                        filter(n_distinct(Numbers)==2))

可以将其更改为具有附加分组列的单个数据集,然后执行相同操作,而不是使用 list

 library(tidyr)
 unnest(my.list, group) %>%
            group_by(group, Letters) %>%
            filter(n_distinct(Numbers)==2)

如果我们不知道每个列表元素中唯一 Numbers 的数量

  unnest(my.list, group) %>% 
              group_by(group) %>% 
              mutate(n= n_distinct(Numbers)) %>%
              group_by(Letters, add=TRUE) %>% 
              filter(n_distinct(Numbers)==n) %>%
              select(-n)

【讨论】:

  • 第一段代码完美运行!绝对精彩。
  • @thatcher1986 很高兴知道它有效。您能否像我在 cmets 中所说的那样消除混乱
猜你喜欢
  • 2021-08-28
  • 1970-01-01
  • 2015-06-06
  • 1970-01-01
  • 2012-12-31
  • 1970-01-01
  • 1970-01-01
  • 2021-08-26
相关资源
最近更新 更多