R 将一行与所有其他行进行比较
我在R中有以下数据帧R 将一行与所有其他行进行比较,r,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
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
我想找到的是行
和层
值相等,同时间隔
应该是一个奇数
数,两个相同的行和层
条目之间的间隔差应该是2
例如
以上两行限定了我的条件行和层与间隔
相同,为奇数,两个间隔
之间的差值为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中完成它?我们可以使用
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
库(data.table)
i1一种不同的方法。你提到你只需要一个唯一的标识符。如果数字不必是连续的,可以这样实现:
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]
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 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
希望这有帮助 我写了这个蹩脚的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
}
}
}
}
}
}
}
使用tidyverse
,您可以尝试以下操作:
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]
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
ID间隔行层flg
1 1 1 2 80 1
2 2 3 2 80 1
3 3 2 5 6 NA
4 4 5 6 NA
5 5 23 6 82 2
6 6 25 6 82 2
7724682NA
884128NA
您可以按如下方式获得子集
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
为了拿到国旗
df$flag <- cumsum(c(1, diff(which(ind)) != 1))[match(df$ID, df1$ID)]
df
如果将ID
编号7的bay
更改为27,则第二种方法将失败。您没有检查2
差异条件。实际上,您的两种方法都无法满足该条件。@Florian我们如何在dplyr方法中添加2
差异条件?@Floriandplyr
方法很简单。如果我们可以在约定的条件中添加2的差异,那么可以很容易地使用lag()检查差异。我会看看我是否能做到这一点。你想如何处理一组中连续3行满足条件的情况?向上投票,因为似乎是唯一一个彻底阅读了问题的人,而不是像我一样试图复制预期的输出。老实说,这就是我喜欢%%>%%
操作符的原因。@Aramis7d介意删除您的评论吗?这个问题已经解决了。谢谢
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