使用基于条件的dplyr作为循环进行过滤

时间:2018-01-27 11:52:10

标签: r dataframe dplyr

我有两个数据框。 DF1

    col1
 1  apples
 2 oranges
 3  apples
 4  banana

和df2

   setID    col1
1      1  apples
2      1 oranges
3      1  apples
4      1  banana
5      2  apples
6      2 oranges
7      2 oranges
8      2  apples
9      3 oranges
10     3  grapes
11     3  banana
12     3  banana
13     4  apples
21     4  oranges
31     4  apples
41     4 oranges

我使用了来自dplyr包的过滤器来缩小df2 df1 $ col1 [1]并将结果放入tempdf

> tempdf <- df2 %>% group_by(setID) %>% filter(any(col1==df1$col1[1]))
> tempdf
    # A tibble: 12 x 2
# Groups:   setID [3]
   setID    col1
   <dbl>   <chr>
 1     1  apples
 2     1 oranges
 3     1  apples
 4     1  banana
 5     2  apples
 6     2 banana
 7     2 oranges
 8     2  apples
 9     4  apples
10     4  oranges
11     4  grapes
12     4 oranges

需要按setID分组,因为我试图查看哪个setID与df1最匹配。由于setID = 3没有任何苹果,因此在第一次迭代中将其省略。我希望这是一个循环,以便每次运行时tempdf都会被更多地过滤掉。

对于下一个元素,它应该是df1 $ col1 [1:2],以便它按顺序检查“apples”和“oranges”。所以在第二次迭代之后,tempdf看起来应该是这样的。

setID    col1
   <dbl>   <chr>
 1     1  apples
 2     1 oranges
 3     1  apples
 4     1  banana
 5     4  apples
 6     4  oranges
 7     4  grapes
 8     4 oranges

下一次迭代应检查df1 $ col1 [2:3],以便它始终检查前一个元素。这次是“橘子”和“苹果”。

 setID    col1
   <dbl>   <chr>
 1     1  apples
 2     1 oranges
 3     1  apples
 4     1  banana

一旦它达到一个唯一的setID,循环就应该结束。结果是df1与df2的setID = 1匹配。

2 个答案:

答案 0 :(得分:1)

以下是过滤setID的一个想法。在这种情况下,它将直接返回setID为1而没有循环。缺点是,如果col1中的所有项目都没有完全匹配,则不会返回任何结果。但是,它应该比for循环方法快得多。

library(dplyr)

df3 <- df1 %>% summarise(col1 = toString(col1))

df4 <- df2 %>%
  group_by(setID) %>%
  summarise(col1 = toString(col1)) %>%
  semi_join(df3, by = "col1")
df4
# # A tibble: 1 x 2
#   setID col1                           
#   <int> <chr>                          
# 1     1 apples, oranges, apples, banana

数据

df1 <- read.table(text = "    col1
 1  apples
                  2 oranges
                  3  apples
                  4  banana",
                  header = TRUE, stringsAsFactors = FALSE)

df2 <- read.table(text = "   setID    col1
1      1  apples
                  2      1 oranges
                  3      1  apples
                  4      1  banana
                  5      2  apples
                  6      2 oranges
                  7      2 oranges
                  8      2  apples
                  9      3 oranges
                  10     3  grapes
                  11     3  banana
                  12     3  banana
                  13     4  apples
                  21     4  oranges
                  31     4  apples
                  41     4 oranges",
                  header = TRUE, stringsAsFactors = FALSE)

答案 1 :(得分:1)

解决方案可以基于选择col1上具有最大匹配的setID

df2 %>% group_by(setID) %>% mutate( maxMatch = sum(col1==df1$col1)) %>% 
  ungroup() %>%
   filter(maxMatch == max(maxMatch)) %>%
  select(-maxMatch)

#Result
# A tibble: 4 x 2
  setID col1   
  <int> <chr>  
1     1 apples 
2     1 oranges
3     1 apples 
4     1 banana