2016-07-05 60 views
1

我有一列第1列(標題爲「日期」的列)中的日期以及第1列和第2列中的值(標題爲「A」和「B」 )。 DFR:列中重複的值,如何用單個值替換

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 

什麼是做到這一點的最好方法是什麼? 謝謝!

回答

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,但第一個除外。除了每個重複塊的第一個值之外,您可以選擇重複的值。

+0

什麼 「RLEID」 功能? –

+0

找不到函數「rleid」 –

+0

您加載了「data.table'包嗎?它來自'data.table'包。 – Psidom

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

謝謝你的這種方法! –

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) 
+0

謝謝你的這種方法! –