当另一列值更改时替换列值

问题描述 投票:0回答:3

在下面的数据中,我想跟踪UValue列。一旦列Value的值在U列中具有相同值的行发生更改,我想为U列分配NA

有关如何有效处理此问题的任何建议?

输入数据

data <- read.table(header = TRUE, text="
U   Value   Debug
A   1     1231
A   1     41
A   2     -1149
A   2     -2339
B   3     -3529
B   4     -4719
C   5     -5909
C   5     -7099
C   5     -8289
C   6     -9479
C   6     -10669
C   6     -11859
D   7     -13049
D   7     -14239
D   8     -15429
D   8     -16619")

当前表输出

U   Value   Debug
A   1   1231
A   1   41
A   2   -1149
A   2   -2339
B   3   -3529
B   4   -4719
C   5   -5909
C   5   -7099
C   5   -8289
C   6   -9479
C   6   -10669
C   6   -11859
D   7   -13049
D   7   -14239
D   8   -15429
D   8   -16619

预期的表输出

U   Value   Debug
A   1   1231
A   1   41
NA  2   -1149
NA  2   -2339
B   3   -3529
NA  4   -4719
C   5   -5909
C   5   -7099
C   5   -8289
NA  6   -9479
NA  6   -10669
NA  6   -11859
D   7   -13049
D   7   -14239
NA  8   -15429
NA  8   -16619

r dataframe
3个回答
1
投票

我们可以使用data.table。将data.frame转换为data.tablesetDT(data)),按U分组,获取Value列的运行长度id(基于值的变化,rleid - 增量值),将其转换为带有mod运算符的二进制(%%),通过否定(!)转换为逻辑,使得0成为TRUE和1的FALSE,得到TRUE值的行指数(.I),提取该列($V1)并使用它作为i来指定(:=U的值NA

library(data.table)
setDT(data)[data[, .I[!rleid(Value) %%2], U]$V1, U := NA]
data
#       U Value  Debug
# 1:    A     1   1231
# 2:    A     1     41
# 3: <NA>     2  -1149
# 4: <NA>     2  -2339
# 5:    B     3  -3529
# 6: <NA>     4  -4719
# 7:    C     5  -5909
# 8:    C     5  -7099
# 9:    C     5  -8289
#10: <NA>     6  -9479
#11: <NA>     6 -10669
#12: <NA>     6 -11859
#13:    D     7 -13049
#14:    D     7 -14239
#15: <NA>     8 -15429
#16: <NA>     8 -16619

Update

根据与OP的讨论,我们需要指定NA'U',其中'Value'不是每个'U'的first'Value'

setDT(data)[data[,  .I[Value != first(Value)], .(U)]$V1, U := NA]

或者在dplyr中使用相同的逻辑

library(dplyr)
data %>% 
   group_by(U1 = U) %>%
   mutate(U = replace(U, Value != first(Value), NA)) %>%
   ungroup %>% 
   select(-U1)

1
投票

像这样的东西?

data %>%
    group_by(U) %>%
    mutate(
        grp = cumsum(!(lag(Value, default = F) == Value)),
        U.new = ifelse(grp == 1, as.character(U), NA))
## A tibble: 16 x 5
## Groups:   U [4]
#   U     Value  Debug   grp U.new
#   <fct> <int>  <int> <int> <chr>
# 1 A         1   1231     1 A
# 2 A         1     41     1 A
# 3 A         2  -1149     2 NA
# 4 A         2  -2339     2 NA
# 5 B         3  -3529     1 B
# 6 B         4  -4719     2 NA
# 7 C         5  -5909     1 C
# 8 C         5  -7099     1 C
# 9 C         5  -8289     1 C
#10 C         6  -9479     2 NA
#11 C         6 -10669     2 NA
#12 C         6 -11859     2 NA
#13 D         7 -13049     1 D
#14 D         7 -14239     1 D
#15 D         8 -15429     2 NA
#16 D         8 -16619     2 NA

我正在这里创建一个新的列U.new,因为我们正在由U进行分组。


在回应你的评论时,你可以用U取代U.new

data %>%
    group_by(U) %>%
    mutate(
        grp = cumsum(!(lag(Value, default = F) == Value)),
        U.new = if_else(grp == 1, as.character(U), "NA")) %>%
    ungroup() %>%
    select(U = U.new, Value, Debug)
## A tibble: 16 x 3
#   U     Value  Debug
#   <chr> <int>  <int>
# 1 A         1   1231
# 2 A         1     41
# 3 NA        2  -1149
# 4 NA        2  -2339
# 5 B         3  -3529
# 6 NA        4  -4719
# 7 C         5  -5909
# 8 C         5  -7099
# 9 C         5  -8289
#10 NA        6  -9479
#11 NA        6 -10669
#12 NA        6 -11859
#13 D         7 -13049
#14 D         7 -14239
#15 NA        8 -15429
#16 NA        8 -16619

0
投票

dplyr的另一个选择是每个组(U)找到Value与前一个不同的第一行,然后将这些行更改为NA

library(dplyr)

data %>%
  group_by(U) %>%
  mutate(U1 = replace(U, row_number() > which.max(diff(Value) != 0), NA))

#   U     Value  Debug U1   
#   <fct> <int>  <int> <fct>
# 1 A         1   1231 A    
# 2 A         1     41 A    
# 3 A         2  -1149 NA   
# 4 A         2  -2339 NA   
# 5 B         3  -3529 B    
# 6 B         4  -4719 NA   
# 7 C         5  -5909 C    
# 8 C         5  -7099 C    
# 9 C         5  -8289 C    
#10 C         6  -9479 NA   
#11 C         6 -10669 NA   
#12 C         6 -11859 NA   
#13 D         7 -13049 D    
#14 D         7 -14239 D    
#15 D         8 -15429 NA   
#16 D         8 -16619 NA   

如果在Value列中可能存在非数字值,我们可以使用lag而不是diff

data %>%
  group_by(U) %>%
  mutate(U1 = replace(U, row_number() >= which.max(Value != lag(Value)), NA))
© www.soinside.com 2019 - 2024. All rights reserved.