将一行与所有其他行进行比较

时间:2017-08-10 12:00:28

标签: r

我在R

中有以下数据框
  ID     bay    row    tier
  1       1      2      80
  2       3      2      80
  3       2      5      06
  4       4      5      06
  5       23     6      82
  6       25     6      82
  7       24     6      82
  8       4      12     08

我想要找到的是rowtier值是相等的,同时bay应该是odd个数字和两个相同row and tier之间的差异1}}条目应为2

E.g

 ID     bay    row    tier
 1       1      2      80
 2       3      2      80

以上两行符合我的条件row and tierbay相同,因为奇数和two bay数字之间的差异为2,我需要生成一个标记为两行生成,让我们说1,2,3唯一标识对

我想要的数据框是

 ID     bay    row    tier   flag
 1       1      2      80     1
 2       3      2      80     1
 3       2      5      06     NA
 4       4      5      06     NA
 5       23     6      82     2
 6       25     6      82     2
 7       24     6      82     NA
 8       4      12     08     NA

我怎样才能在r?

中这样做

5 个答案:

答案 0 :(得分:3)

您可以按如下方式获取子集,

ind <- duplicated(df[c('row', 'tier')]) & df$bay%%2 == 1|
       duplicated(df[c('row', 'tier')], fromLast = TRUE) & df$bay%%2 == 1
df1 <- df[ind,]
df1 <- df1[!!with(df1, ave(bay, new, FUN = function(i) c(TRUE, diff(i) == 2))),]
df1

哪个给出了

  ID bay row tier
1  1   1   2   80
2  2   3   2   80
5  5  23   6   82
6  6  25   6   82

要获得旗帜,

df$flag <- cumsum(c(1, diff(which(ind)) != 1))[match(df$ID, df1$ID)]
df

由此给出,

ID bay row tier flag
1  1   1   2   80    1
2  2   3   2   80    1
3  3   2   5    6   NA
4  4   4   5    6   NA
5  5  23   6   82    2
6  6  25   6   82    2
7  7  24   6   82   NA
8  8   4  12    8   NA

答案 1 :(得分:2)

使用tidyverse,你可以尝试这样的事情:

df %>%
  group_by(row,tier) %>%
  mutate(flg = if_else(bay %%2 >0, 1, 0)) %>%
  filter(flg == 1) %>%
  mutate(df2 = lead(bay,1) - bay) %>%
  filter(df2 == 2) %>%
  select(-df2) %>%
  ungroup()%>%
  mutate(flg = 1:n()) %>%
  right_join(df) %>%
  mutate(flg = coalesce(flg,lag(flg,1)))

给出:

     ID   bay   row  tier   flg
  <int> <int> <int> <int> <int>
1     1     1     2    80     1
2     2     3     2    80     1
3     3     2     5     6    NA
4     4     4     5     6    NA
5     5    23     6    82     2
6     6    25     6    82     2
7     7    24     6    82    NA
8     8     4    12     8    NA

答案 2 :(得分:1)

我们可以使用

library(data.table)
i1 <- setDT(df1)[, .I[all(bay%%2 == 1) & diff(bay)==2], .(grp = rleid(bay%%2),row, tier)]$V1
df1[i1, flag := 1
  ][!is.na(flag), flag := as.numeric(.GRP), .(row, tier)]
df1
#    ID bay row tier flag
#1:  1   1   2   80    1
#2:  2   3   2   80    1
#3:  3   2   5    6   NA
#4:  4   4   5    6   NA
#5:  5  23   6   82    2
#6:  6  25   6   82    2
#7:  7  24   6   82   NA
#8:  8   4  12    8   NA

答案 3 :(得分:1)

一种不同的方法。你提到你只需要一个唯一的标识符。如果数字不必是连续的,则可以这样实现:

library(dplyr)
df$flag=NA
group = df %>% group_indices(row,tier)
idx = which(df$bay %% 2==1 & (df$bay - lag(df$bay,default=-1)==2 | group != lag(group,default=-1)))
df$flag[idx]=group[idx]

输出:

  ID bay row tier flag
1  1   1   2   80    1
2  2   3   2   80    1
3  3   2   5    6   NA
4  4   4   5    6   NA
5  5  23   6   82    3
6  6  25   6   82    3
7  7  24   6   82   NA
8  8   4  12    8   NA

希望这有帮助!

答案 4 :(得分:0)

我写了这个蹩脚的for循环,但它的工作原理

df$flag = NA

for(i in 1:nrow(df)) {
  for(j in 2:nrow(df)) {
    if(df$row[i] == df$row[j]){
      if(df$tier[i] == df$tier[j]){
        if(df$bay[i] %% 2 != 0){
          if(df$bay[j] %% 2 != 0){
            if(abs(df$bay[i] - df$bay[j]) == 2){
              df$flag[i] = i
              df$flag[j] = i
         }
       }

      }
    }
   }
  }
 }