仅标记r中每个id的列值第一次按行变化



我就开门见山了。我在stackoverflow上发现了一些部分有效的代码。

df1 <- read.table(text = "
ID  V1    V2
A   X     SBI123
A   Y     SBI123
A   Y     SBI133
B   A     SBI888
B   A     SBI999
B   B     SBI999
", header = TRUE)
# Rowwise comparison per column
setDT(df1)[, flag_V1 := 0][V1!="", flag_V1 := 1*(rleid(V1)-1 > 0), by = ID]
setDT(df1)[, flag_V2 := 0][V2!="", flag_V2 := 1*(rleid(V2)-1 > 0), by = ID]
df1
# Output
ID V1     V2 flag_V1 flag_V2
1:  A  X SBI123       0       0
2:  A  Y SBI123       1       0
3:  A  Y SBI133       1       1
4:  B  A SBI888       0       0
5:  B  A SBI999       0       1
6:  B  B SBI999       1       1

所以ID 'A'的V1值第一次改变'flag_V1'是1,这是正确的。我想让第三条线等于0。我明白,代码比较所有列值的第一行,这使得这段代码正确,但我只希望第一次值的变化被标记。期望的输出:

# Desired output
ID V1     V2 flag_V1 flag_V2
1:  A  X SBI123       0       0
2:  A  Y SBI123       1       0
3:  A  Y SBI133       0       1
4:  B  A SBI888       0       0
5:  B  A SBI999       0       1
6:  B  B SBI999       1       0

在"dplyr"中,可以使用"across"one_answers"lag"。基本上,当前一个值与实际值不同时,该值为1,否则为0。

library(dplyr)
df1 %>% 
group_by(ID) %>% 
mutate(across(V1:V2, ~ +(lag(.x, default = first(.x)) != .x), .names = "flag_{col}"))
# A tibble: 6 × 5
# Groups:   ID [2]
ID    V1    V2     flag_V1 flag_V2
<chr> <chr> <chr>    <int>   <int>
1 A     X     SBI123       0       0
2 A     Y     SBI123       1       0
3 A     Y     SBI133       0       1
4 B     A     SBI888       0       0
5 B     A     SBI999       0       1
6 B     B     SBI999       1       0

您可以将重复项转换为0,即对于V1

library(data.table)
setDT(df1)[, flag_V1 := 0][
V1!="", flag_V1 := 1*(rleid(V1)-1 > 0), by = ID][, 
lapply(.SD, function(i) replace(i, duplicated(i), 0)), by = .(ID, V1)][]
ID V1     V2 flag_V1
1:  A  X SBI123       0
2:  A  Y SBI123       1
3:  A  Y SBI133       0
4:  B  A SBI888       0
5:  B  A SBI999       0
6:  B  B SBI999       1

相关内容

最新更新