2017-01-23 54 views
0

我有一個非常類似的問題來替換重複值在數據框中。在從其它列中的數據幀使用向量標準

我有這樣一個數據幀(加上一些額外的列):

ID<- c("1V","1V","1V","1V","2V","2V","4V","4V","4V","4V","4V") 
year<- c(1,1,1,2,1,1,2,2,3,3,3) 
sequence<- c(1,2,2,1, 1,2,1,2,1,1,1) 
score <- c(5,5,5,5,10,10,10,10,11,11,11) 
examp <- data.frame(ID,year, sequence, score) 

> examp 
    ID year sequence score 
1 1V 1  1  5 
2 1V 1  2  5 
3 1V 1  2  5 
4 1V 2  1  5 
5 2V 1  1 10 
6 2V 1  2 10 
7 4V 2  1 10 
8 4V 2  2 10 
9 4V 3  1 11 
10 4V 3  1 11 
11 4V 3  1 11 

我需要的是每個ID,年份和順序與NA內更換重複的分數。此外,評分序列與評分應該用NA代替。因此,沒有行被刪除,只有特定的條目。

> examp 
    ID year sequence score 
1 1V 1  1  5 
2 1V 1  2  5 
3 1V 1  NA NA 
4 1V 2  2  5 
5 2V 1  1 10 
6 2V 1  2 10 
7 4V 2  1 10 
8 4V 2  2 10 
9 4V 3  1 11 
10 4V 3  NA NA 
11 4V 3  NA NA 

保留所有行。不同ID /年/序列可能會出現相同的分數,但只有在這三列的每個獨特組合中,我才能取代重複分數。

實施例與來自其它鏈接的問題的單個載體和溶液:

a <- 1 1 1 2 3 2 2 2 2 1 0 0 0 0 2 3 4 4 1 1 
ifelse(a == c(a[1]-1,a[(1:length(a)-1)]) , 0 , a) 
[1] 1 0 0 2 3 2 0 0 0 1 0 0 0 0 2 3 4 0 1 0 

我不確定如何適應上面的代碼中的問題上面多個標準。可能嗎? 主要是,最重要的是取代分數,但如果有人有解決方案來取代分數和序列,我會很高興。

回答

1

在基礎R,您可以使用子集和is.na

is.na(examp[duplicated(examp[1:3]), c("sequence", "score")]) <- TRUE 

examp 
    ID year sequence score 
1 1V 1  1  5 
2 1V 1  2  5 
3 1V 1  NA NA 
4 1V 2  1  5 
5 2V 1  1 10 
6 2V 1  2 10 
7 4V 2  1 10 
8 4V 2  2 10 
9 4V 3  1 11 
10 4V 3  NA NA 
11 4V 3  NA NA 

這裏,ID year sequence返回一個邏輯向量的data.frame的發信號的前三個變量的行是否是以前的行的重複長度。 c("sequence", "score")確定要被替換的列。然後is.na在這些列中被設置爲TRUE以表示重複的行。

更長,但更具可讀性的版本是使用變量名稱而不是它們的位置。

is.na(examp[duplicated(examp[c("ID", "year", "sequence")]), c("sequence", "score")]) <- TRUE 

從長遠來看,由於合併或其他操作導致頭寸移動,這也更安全。在從現在起六個月的時間內審查代碼時,閱讀/解讀也可能更容易。

+0

謝謝,這很簡單,完美地工作! – Lisarv

0

我們可以使用data.table。將'data.frame'轉換爲'data.table'(setDT(examp)),按'ID'分組,'year',我們得到行索引(.I),其中列'sequence'爲duplicated,然後set這些值在數據集列'序列','分數'爲NA。這應該是非常有效的,因爲我們在地方

library(data.table) 
i1 <- setDT(examp)[, .I[duplicated(sequence)], .(ID, year)]$V1 
for(j in 3:4){ 
    set(examp, i = i1, j=j, value = NA) 
} 

examp 
# ID year sequence score 
# 1: 1V 1  1  5 
# 2: 1V 1  2  5 
# 3: 1V 1  NA NA 
# 4: 1V 2  1  5 
# 5: 2V 1  1 10 
# 6: 2V 1  2 10 
# 7: 4V 2  1 10 
# 8: 4V 2  2 10 
# 9: 4V 3  1 11 
#10: 4V 3  NA NA 
#11: 4V 3  NA NA 

或用dplyr

library(dplyr) 
examp %>% 
    group_by(ID, year) %>% 
    mutate_each(funs(replace(., duplicated(.), NA))) 

隨着base R設置,我們可以做一個小巧的選

examp[duplicated(examp[1:3]), 3:4] <- NA 
examp 
# ID year sequence score 
#1 1V 1  1  5 
#2 1V 1  2  5 
#3 1V 1  NA NA 
#4 1V 2  1  5 
#5 2V 1  1 10 
#6 2V 1  2 10 
#7 4V 2  1 10 
#8 4V 2  2 10 
#9 4V 3  1 11 
#10 4V 3  NA NA 
#11 4V 3  NA NA 

或者另一個操作重刑是replacelapply

examp[3:4] <- lapply(examp[3:4], function(x) replace(x, duplicated(examp[1:3]), NA)) 
相關問題