如何在R中找到满足多个条件的值的交集?

Dir*_*tke 11 r dataframe

假设我有以下数据框:

df <- data.frame(year=c(2010,2011,2012,2010,2011,2010,2011,2012), company = c("a","a","a","b","b","c","c","c"))

  year company
1 2010       a
2 2011       a
3 2012       a
4 2010       b
5 2011       b
6 2010       c
7 2011       c
8 2012       c

Run Code Online (Sandbox Code Playgroud)

我想找到这三年中都存在的公司。一种麻烦的方法是:

library(dplyr)

companies_2010 <- df %>% filter(year==2010) %>% select(company)
companies_2011 <- df %>% filter(year==2011) %>% select(company)
companies_2012 <- df %>% filter(year==2012) %>% select(company)

companies <- intersect(companies_2010, companies_2011) %>% intersect(., companies_2012)

  company
1       a
2       c
Run Code Online (Sandbox Code Playgroud)

有没有更优雅的方法来做到这一点?

G. *_*eck 8

由于年份不同并且在所需的集合中,我们只需计算每个公司有多少个年份即可。(如果情况并非如此,一般来说,则应用下面的解决方案来df2 <- unique(merge(df, data.frame(year = 2010:2012)))代替 df。此外,如果我们不知道值 3 并且我们希望它等于数据中的唯一年份数,那么我们可以使用以下方法计算它length(unique(df$year))

现在,使用这个想法有几种选择。我们可以使用 table 来获取它们的频率,然后保留频率为 3 的频率,或者在最后一种情况下,我们可以使用 dplyr 的计数,然后过滤以获得频率为 3 的频率。

tab <- table(df$company)
names(tab)[tab == 3]
## [1] "a" "c"

names(Filter(function(x) x == 3, table(df$company)))
## [1] "a" "c"

library(dplyr)   
df %>%
  count(company) %>%
  filter(n == 3) %>%
  select(company)
##   company
## 1       a
## 2       c
Run Code Online (Sandbox Code Playgroud)

使用问题的相交思想按年份拆分公司,然后使用Reduce重复应用相交:

 with(df, Reduce(intersect, split(company, year)))
 ## [1] "a" "c"
Run Code Online (Sandbox Code Playgroud)

我们可以使用这样的表格来可视化这一点。任何没有零值的列都对应于具有所有年份的公司。

table(df)
##       company
## year   a b c
##   2010 1 1 1
##   2011 1 1 1
##   2012 1 0 1
Run Code Online (Sandbox Code Playgroud)

或存在绿色且不存在红色的热图。任何完全绿色的柱子都有年份。

heatmap(table(df), Rowv = NA, Colv = NA, col = 2:3, scale = "none")
Run Code Online (Sandbox Code Playgroud)

截屏


Rui*_*das 5

ave这是带有和的基本 R 解unique

n <- with(df, ave(year, company, FUN = length))
unique(df$company[n == 3])
#[1] "a" "c"
Run Code Online (Sandbox Code Playgroud)


Ano*_*n R 5

既然您收到了一些出色的答案,我认为带有一点想象力的非常不同的方法也可能很好。

我将您的问题可视化为二分图,其中我们有两组不同的节点,其中一个是公司名称,另一个是年份,而公司之间以及年份之间没有联系。

library(igraph)

# Creating a graph object but first I alternate the columns of your data set
df[, c(2, 1)] |>
  graph_from_data_frame() -> g

# Then we create a type object to distinguish between 2 sets of nodes, Type FALSE
# refers to company name and type TRUE refers to years
V(g)$type <- bipartite.mapping(g)$type

# Then we extract those nodes whose degree are equal to 3 while they are of type FALSE
V(g)[degree(g, V(g)) == length(unique(df$year)) & V(g)$type == FALSE]
+ 2/6 vertices, named, from c172916:
[1] a c
Run Code Online (Sandbox Code Playgroud)

如果您想查看图表的外观:

plot(g,
     vertex.color = ifelse(V(g)$type, "lightblue", "salmon"),
     vertex.shape = ifelse(V(g)$type, "circle", "square"),
     vertex.size = 25,
     edge.color = "grey",
     layout = layout.bipartite)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


Ben*_*ker 4

这通常不起作用计算任意交点,但是 (\xc2\xbf 我认为?) 会执行您上面指定的操作:

\n
(df \n   %>% group_by(company)\n   %>% filter(all(2010:2012 %in% year))\n   %>% select(company)\n   %>% distinct()\n)\n
Run Code Online (Sandbox Code Playgroud)\n