查找列表中的公共元素

时间:2018-04-07 07:30:39

标签: r

假设我有3个字符向量。我想对它们进行一些评估,比如是否也在其他向量中找到向量中的元素。我不知道哪个向量是最短的,所以我想以编程方式计算它。

例如:

a <- c('Name','Type')
b <- c('Name','Age','Meta')
c <- c('ID','Gender','Color')

l1 <- list(a,b,c)
#print(l1)
l2 <- sapply(l1,length)
#print(l2)

pos <- which(l2==min(l2))
shortest <- l1[pos]
#print(shortest)

a1 <- l1[!seq(1,3) %in% pos][1]
a2 <- l1[!seq(1,3) %in% pos][2]
#print(a1)
#print(a2)

shortest[[1]][sapply(shortest,function(x) !x %in% unlist(c(a1,a2)))[,1]]

我想找到最短元素中的元素,但在其他两个元素中找不到。在这个例子中,我希望得到'Type'作为结果。我也遇到了两个元素满足最小长度的情况的问题(在这个例子中长度是2,3,3但我想处理2,2,3。会感谢一些帮助。我需要在11000个列表中运行这个l1,我的矢量长度最小为20。

3 个答案:

答案 0 :(得分:2)

一种方法是通过最少数量的元素和单词的最低频率来形成列表元素的数据帧,然后filter。这也将捕获同一向量中多个唯一单词的实例。

library(tidyverse)
l1 %>% enframe() %>% unnest() %>%
  group_by(name) %>%
  mutate(list_n = n()) %>%
  ungroup() %>%
  group_by(value) %>%
  mutate(not_in = n()) %>%
  ungroup() %>%
  filter(list_n == min(list_n) & not_in == 1) %>%
  select(-list_n, -not_in)

# # A tibble: 1 x 2
#    name value
#   <int> <chr>
# 1     1 Type 

答案 1 :(得分:2)

将数据整理成观察矢量和分组变量,在data.frame中协调

df = data.frame(
    word = unlist(l1),
    group = rep(seq_along(l1), lengths(l1)),
    stringsAsFactors = FALSE
)

lengths()是实施sapply(x, length))的更有效方式。

使用您需要的信息处理数据 - 每个组的长度以及每个单词的计数

df = cbind(df,
    word_count = as.vector(table(df$word)[df$word]),
    group_length = tabulate(df$group)[df$group]
)

通过按字数排序,然后按组长度

排序行来对所需结果进行建模
df[order(df$word_count, df$group_length),]

答案是第一行

> df[order(df$word_count, df$group_length),]
    word group word_count group_length
2   Type     1          1            2
4    Age     2          1            3
5   Meta     2          1            3
6     ID     3          1            3
7 Gender     3          1            3
8  Color     3          1            3
1   Name     1          2            2
3   Name     2          2            3

使用不同的指标处理关系以建模数据;如何实现这取决于你想要使用的模型。

这与@ hpesoj626与'整洁'步骤

基本相同
tidy <- l1 %>% enframe() %>% unnest()

'操纵'步骤

manip <- tidy %>%
  group_by(name) %>% mutate(list_n = n()) %>% ungroup() %>%
  group_by(value) %>% mutate(not_in = n()) %>% ungroup()

和'模型'步骤

manip %>% filter(list_n == min(list_n) & not_in == 1) %>%
  select(-list_n, -not_in)

答案 2 :(得分:1)

请查看原始帖子的一些修改,包括添加一个也有两个元素的供应商'd',因此与原始矢量'a'的关系最短。如果我理解你的需要,那么在矢量最短的情况下,他们会返回所有其他元素中的非匹配元素,这些元素与那些最短的元素不匹配(也就是说,在这个例子中,你不要我不想比较'a'和'd',因为它们都是最短的;而你想把它们与'b'和'c'进行比较。

下面的解决方案使用setdiff()函数来识别和返回差异。它还将所有非最短向量组合成一个唯一元素向量,以便同时进行比较,而不是分别迭代每个非最短向量。

a <- c('Name','Type')
b <- c('Name','Age','Meta')
c <- c('ID','Gender','Color')
d <- c('Name','Reason')

l1 <- list(a,b,c,d)
l2 <- sapply(l1,length)

pos <- which(l2==min(l2))
shortest <- l1[pos]

#All the lists that are not the shortest ones
not_shortest <- l1[-pos]

#Collapse all the lists we want to search through into a single vector of unique elements
all_not_shortest <- unique(unlist(not_shortest))

#All of the shortest vectors (here 'a' and 'd' tie for shortest) compare their element differences to the entire set of all elements in not shortest vectors
lapply(shortest,setdiff,all_not_shortest)