我就开门见山了。我在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