R:列中的重复值,如何用单个值替换

时间:2016-07-05 16:56:50

标签: r

我在第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

最好的方法是什么? 谢谢!

3 个答案:

答案 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)