2014-10-17 27 views
0

我試圖將行追加到R df。下面是一個例子DF FOO:R:基於多列中的值添加零行

A B C D 
1 1 1 200 
1 1 2 50 
1 1 3 15 
1 2 1 150 
1 2 4 50 
1 3 1 300 
2 1 2 40 
2 1 4 90 
2 3 2 80 

對於每一個A,有B的3個可能的值,以及對於每個B,有C的4個可能的值。然而,最初的DF只包含非零值D.我想操作df,以便B和C都包含零。因此,df對於任何B/C值爲0的D都會顯示0。我已經看到了解決這個問題的問題一列,但無法找到解決它與多列的問題。最終的DF應該是這樣的:

A B C D 
1 1 1 200 
1 1 2 50 
1 1 3 15 
1 1 4 0 
1 2 1 150 
1 2 2 0 
1 2 3 0 
1 2 4 50 
1 3 1 300 
1 3 2 0 
1 3 3 0 
1 3 4 0 
2 1 1 0 
2 1 2 40 
2 1 3 0 
2 1 4 90 
2 2 1 0 
2 2 2 0 
2 2 3 0 
2 2 4 0 
2 3 1 0 
2 3 2 80 
2 3 3 0 
2 3 4 0 

我第一次嘗試創建一個虛擬的數據幀,然後與初始DF合併的事,但不工作的權利。這裏是當前的代碼,我知道是錯誤的,因爲這段代碼只生成基於A的行。我想我想製作基於A和B的虛擬框架,但我不知道如何 - if/else函數可以在這裏工作?:

# create dummy df 
dummy <- as.data.frame(
    cbind(
    sort(rep(unique(foo$A), 12)), 
    rep(1:3,length(unique(foo$A))))) 
colnames(dummy) <- c("A","B") 
foo$A <- as.numeric(foo$A) 
foo$B <- as.numeric(foo$C) 

# merge with foo 
mergedummy <- merge(dummy,foo,all.x=T) 

任何有識之士,非常感謝 - 謝謝!

回答

5

一個一個班輪:

merge(dat, data.frame(table(dat[1:3]))[-4],all.y=TRUE) 

# A B C D 
#1 1 1 1 200 
#2 1 1 2 50 
#3 1 1 3 15 
#4 1 1 4 NA 
#... 

或者,也許不那麼複雜:

out <- data.frame(xtabs(D ~ ., data=dat)) 
out[do.call(order,out[1:3]),] 

# A B C Freq 
#1 1 1 1 200 
#7 1 1 2 50 
#13 1 1 3 15 
#19 1 1 4 0 
#... 

其中dat是:

dat <- structure(list(A = c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L), B = c(1L, 
1L, 1L, 2L, 2L, 3L, 1L, 1L, 3L), C = c(1L, 2L, 3L, 1L, 4L, 1L, 
2L, 4L, 2L), D = c(200L, 50L, 15L, 150L, 50L, 300L, 40L, 90L, 
80L)), .Names = c("A", "B", "C", "D"), class = "data.frame", row.names = c(NA, 
-9L)) 
+0

+1但你是否需要第一行中的「do.call」? – 2014-10-17 02:18:00

+0

@KarolisKoncevičius - 不,不,我不知道。發現得好。 – thelatemail 2014-10-17 03:29:14

+0

感謝您的支持!您的第一個單線程工作,然後我添加了一個額外的'df [is.na(df)< - 0'行以用0替換NA。非常感謝。 – ucsbcoding 2014-10-17 12:52:45

3

我創建了一個主數據框,其中包含A,B和C的所有組合,如您在預期結果中所述。然後,我合併主數據框和你的數據框。最後,我換成NA爲0

master <- data.frame(A = rep(1:2, each = 12), 
        B = rep(1:3, each = 4), 
        C = rep(1:4, times = 6)) 

library(dplyr) 

master %>% 
    left_join(., mydf) %>% 
    mutate(D = ifelse(D %in% NA, 0, D)) 

# A B C D 
#1 1 1 1 200 
#2 1 1 2 50 
#3 1 1 3 15 
#4 1 1 4 0 
#5 1 2 1 150 
#6 1 2 2 0 
#7 1 2 3 0 
#8 1 2 4 50 
#9 1 3 1 300 
#10 1 3 2 0 
#11 1 3 3 0 
#12 1 3 4 0 
#13 2 1 1 0 
#14 2 1 2 40 
#15 2 1 3 0 
#16 2 1 4 90 
#17 2 2 1 0 
#18 2 2 2 0 
#19 2 2 3 0 
#20 2 2 4 0 
#21 2 3 1 0 
#22 2 3 2 80 
#23 2 3 3 0 
#24 2 3 4 0 
2

這裏是一種解決方案:

foo <- merge(expand.grid(lapply(foo[,1:3], unique)), foo, all=TRUE, sort=TRUE) 
foo[is.na(foo)] <- 0