2015-03-10 26 views
7

Tôi có một data.table trông như thế nàyTạo hàng trùng lặp dựa trên điều kiện trong R

dt <- data.table(ID=c("A","A","B","B"),Amount1=c(100,200,300,400), 
       Amount2=c(1500,1500,2400,2400),Dupl=c(1,0,1,0)) 

    ID Amount1 Amount2 Dupl 
1: A  100 1500 1 
2: A  200 1500 0 
3: B  300 2400 1 
4: B  400 2400 0 

tôi cần phải lặp lại mỗi hàng có 1 trong cột Dupl và thay thế các giá trị Amount1 với AMOUNT2 giá trị trong hàng trùng lặp đó. Bên cạnh đó tôi cần phải cung cấp cho hàng trùng lặp đó giá trị 2 trong Dupl. Điều này có nghĩa là nó sẽ trông như thế này:

ID Amount1 Amount2 Dupl 
1: A  100 1500 1 
2: A 1500 1500 2 
3: A  200 1500 0 
4: B  300 2400 1 
5: B 2400 2400 2 
6: B  400 2400 0 

Bất kỳ trợ giúp nào được đánh giá cao! Trân trọng!

Tim

+3

Có bất kỳ quy tắc nào khác mà chúng tôi cần biết không? Có thể có bốn hàng cho một ID nhất định không? Cột "Dupl" có các giá trị khác với "1" và "2" không? – A5C1D2H2I1M1N2O1R2T1

Trả lời

9

Bạn có thể thử

rbind(dt,dt[Dupl==1][,c('Amount1', 'Dupl') := list(Amount2, 2)]) 
+0

@DavidArenburg Cảm ơn, tôi cũng đã suy nghĩ về 'rleid' bằng cách sử dụng mã mẫu của bạn, nhưng tìm thấy là một chút khó khăn. – akrun

3

Điều này dường như làm những gì bạn đang yêu cầu. có lẽ có thể được tinh chế một chút ...

library(splitstackshape) 
expandRows(dt, dt$Dupl+1, count.is.col = FALSE)[ 
    Dupl != 0, Dupl := cumsum(Dupl), by = ID][ 
    , Amount1 := ifelse(Dupl > 1, Amount2[-1], Amount1)][] 
# ID Amount1 Amount2 Dupl 
# 1: A  100 1500 1 
# 2: A 1500 1500 2 
# 3: A  200 1500 0 
# 4: B  300 2400 1 
# 5: B 2400 2400 2 
# 6: B  400 2400 0 
6

Sử dụng dplyr

require("data.table") 
require("dplyr") 

#data 
dt <- data.table(ID=c("A","A","B","B"),Amount1=c(100,200,300,400), 
       Amount2=c(1500,1500,2400,2400),Dupl=c(1,0,1,0)) 
#result 
rbind(dt, 
     dt %>% 
     filter(Dupl==1) %>% 
     mutate(Dupl=2, 
       Amount1=Amount2)) 

# ID Amount1 Amount2 Dupl 
# 1: A  100 1500 1 
# 2: A  200 1500 0 
# 3: B  300 2400 1 
# 4: B  400 2400 0 
# 5: A 1500 1500 2 
# 6: B 2400 2400 2 
+0

Tôi luôn cố gắng tránh plyr vì tôi làm việc với các tập dữ liệu lớn, nhưng điều này cũng hiệu quả. Cảm ơn nhiều. –

4

Bạn có thể rbind một bản sao của dữ liệu phụ setted với biến đổi đúng được thực hiện:

rbind(dt,copy(dt[Dupl==1])[,Amount1:=Amount2][,Dupl:=Dupl+1]) 
    ID Amount1 Amount2 Dupl 
1: A  100 1500 1 
2: A  200 1500 0 
3: B  300 2400 1 
4: B  400 2400 0 
5: A 1500 1500 2 
6: B 2400 2400 2 

Ngoài ra, bạn có thể nhận được các bản sao bằng cách thiết lập phụ, và sau đó chuyển đổi các hàng trùng lặp bằng cách sử dụng một bước trung gian. Điều này sẽ giữ hàng trùng lặp bên cạnh ảnh gốc như trong ví dụ trong câu hỏi:

x <- dt[rep(seq(dt[,Dupl]),times=dt[,Dupl==1]+1)] 
x[duplicated(x),c("Amount1","Dupl"):=list(Amount2,Dupl+1)] 
x 
    ID Amount1 Amount2 Dupl 
1: A  100 1500 1 
2: A 1500 1500 2 
3: A  200 1500 0 
4: B  300 2400 1 
5: B 2400 2400 2 
6: B  400 2400 0 
+1

Bạn có thể thực hiện bước đầu tiên trong giải pháp thứ hai chỉ bằng 'x <- dt [rep (seq_len (.N), Dupl + 1L)]'. Nó có vẻ như gọi 'dt' 3 lần trong bước này là một chi phí lớn nếu' dt' lớn. –

Các vấn đề liên quan