我在第1列有一个日期表(标题为#34;日期"列)和第1列和第2列中的值(标题为&#34的列; A"和" B&#34 )。 DF
Date A B
1 1/1/16 X X
2 1/2/16 X Y
3 1/3/16 X Y
4 1/4/16 Y Y
5 1/5/16 Y X
等
我需要创建额外的第4列和第5列A *和B *,其中包含以下内容:
每行:
对于列A * - 如果当前行中A列中的值与上一行中A列中的值不同,则插入新值,如果值相同则不插入任何内容。
对于列B * - 如果当前行中B列中的值与上一行中B列中的值不同,则插入新值,如果值相同则不插入任何内容。
期望的输出:
Date A B A* B*
1 1/1/16 X X X X
2 1/2/16 X Y - Y
3 1/3/16 X Y - -
4 1/4/16 Y Y Y -
5 1/5/16 Y X - X
最好的方法是什么? 谢谢!
答案 0 :(得分:3)
在基础R中,我们可以先使用diff
来识别列中的更改,然后使用ifelse
来计算转换值或"-"
并将结果保存为新列:
df[,c("A*", "B*")] <- lapply(df[-1], function(x) {
ifelse(c(1,diff(as.numeric(as.factor(x)))), as.character(x), "-")})
df
# Date A B A* B*
# 1 1/1/16 X X X X
# 2 1/2/16 X Y - Y
# 3 1/3/16 X Y - -
# 4 1/4/16 Y Y Y -
# 5 1/5/16 Y X - X
虽然奇怪的是数值作为if else函数的条件,但请注意R将所有零转换为FALSE而所有其他数字转换为TRUE
答案 1 :(得分:1)
library(data.table);
df$A1 = ifelse(duplicated(rleid(df$A)), "-", df$A)
df$B1 = ifelse(duplicated(rleid(df$B)), "-", df$B)
df
Date A B A1 B1
1 1/1/16 X X X X
2 1/2/16 X Y - Y
3 1/3/16 X Y - -
4 1/4/16 Y Y Y -
5 1/5/16 Y X - X
注意:rleid
或许代表run length encoding (id?)
。基本上它的作用是为每个重复序列创建一个id。因此,每个重复的序列将被不同地标记。然后使用duplicated
函数将重复值标记为TRUE
,除了第一个。除了每个重复块的第一个值之外,您可以选择重复的值。
答案 2 :(得分:0)
以下是使用rle
函数的基本R方法:
# fill new variable with desired value
df$A1 <- "-"
# fill it in with original value
df$A1[c(1, head(cumsum(rle(df$A)$length), -1)+1)] <- rle(df$A)$value
# repeat for B
df$B1 <- "-"
df$B1[c(1, head(cumsum(rle(df$B)$length), -1)+1)] <- rle(df$B)$value
这导致
df
Date A B A1 B1
1 1/1/16 X X X X
2 1/2/16 X Y - Y
3 1/3/16 X Y - -
4 1/4/16 Y Y Y -
5 1/5/16 Y X - X
请注意,变量A和B必须是字符,这就是我使用下面的as.is = TRUE参数的原因。
数据强>
df <- read.table(header= TRUE, text=" Date A B
1 1/1/16 X X
2 1/2/16 X Y
3 1/3/16 X Y
4 1/4/16 Y Y
5 1/5/16 Y X", as.is=TRUE)