2017-06-15 29 views
3

我有一個數據集,看起來如何在data.table中動態使用lapply?

set.seed(18) 
library(data.table) 
site1 <- data.table(id = 1:10, A = c(sample(c(NA, letters[1:10]),10)), 
        B = sample(c(NA, LETTERS[1:7]), 10, replace = T), 
        C = sample(c(NA, 1:4), 10, replace = T)) 

site2 <- data.table(id = c(1:4, sample(5:15, 6)), 
        A = c(NA, NA, NA, sample(letters, 1), NA, NA, NA, sample(letters, 1), NA, NA), 
        B = sample(LETTERS, 10), d = sample(1:5, replace = T)) 

而且看起來

col.smash <- function(a, b, linkvars){ 
  require(data.table) 
  
  ##### CONVERT TO DATA.TABLES FOR EASIER USE, AND MERGE 
  if(dim(a)[1] <= dim(b)[1]){ 
    c <- data.table(a); setkeyv(c, linkvars) 
    d <- data.table(b); setkeyv(d, linkvars) 
  } else { 
    c <- data.table(b); setkeyv(c, linkvars) 
    d <- data.table(a); setkeyv(d, linkvars) 
  } 
  
  k <- c[d] 
  
  rep.list<- names(a)[names(a) %in% names(b) & !(names(a) %in% linkvars)] 
  i.combo <- paste0("i.",rep.list) 

  f <- k[ , (rep.list) := lapply(.SD, function(x){ifelse(is.na(x), 
                get("i.", names(x)), x)}), 
      .SDcols = rep.list] 
  return(f) 
  } 

此功能的目標是看到在兩種site1site2哪些變量和函數,如果有一個「NA 「中,可以說site1$A,將其替換爲site2$A中的相應值。在site2之上有一個site1的層次結構,這就是爲什麼ifelse語句只檢查一個帶有「NA」的變量。

由於第一個ifelse結果(get("i.",names(x)))在條件不正常工作後出現lapply函數錯誤。這樣做,我得到以下錯誤:

Error in as.environment(pos) : using 'as.environment(NULL)' is defunct 

我不明白。理想情況下,我會得到的是在site1所有值的data.tablesite2與變量ABCD而不是與i.Ai.B因爲如此,

id A B C d 
1: 1 i E NA 4 
2: 2 g F NA 4 
3: 3 h NA 4 1 
4: 4 x B 4 2 
5: 5 j G NA NA 
6: 6 c NA 3 4 
7: 7 a D 2 NA 
8: 8 b NA 2 NA 
9: 9 d G 1 4 
10: 10 f NA 1 NA 
11: 12 NA V NA 2 
12: 13 n J NA 1 
13: 14 NA T NA 1 
14: 15 NA X NA 1 

所以,我想我真的有兩個問題。第一個是錯誤,第二個是我沒有在我的函數中獲得k中的所有行。他們似乎沒有關係。

任何幫助表示讚賞。

另外,布朗尼積分誰可以弄清楚不可思議col.smash參考。

+0

你能做到這一點作爲骨料操作由'='羣體,如果你做一個長data.table通過rbind-ING 'site1'和'site2'在彼此之下。 – thelatemail

+0

只是爲了澄清,你在談論完整的專欄,對吧?措辭_如果有一個「NA」,可以說'site1 $ A',將其替換爲'site2 $ A'_中的相應值,這有點不幸,因爲它表明您正在要求__ row-wise replacement_。但是在這種情況下,預期結果將在列「B」的第3行中顯示「C」,例如, – Uwe

+0

@UweBlock我不理解你的問題。請澄清 – akash87

回答

3

This function's goal is to see what variables are in both site1 and site2 and if there is an "NA" in, lets say site1$A , replace it with the corresponding value in site2$A . There is a hierarchy of site1 over site2

輸出可以有一個像

g <- function(d1, d2, byvars){ 
    D = funion(d1[, ..byvars], d2[, ..byvars]) 

    d2vars = setdiff(names(d2), byvars) 
    D[d2, on=byvars, (d2vars) := mget(sprintf("i.%s", d2vars))] 

    d1vars = setdiff(names(d1), byvars) 
    D[d1, on=byvars, (d1vars) := mget(sprintf("i.%s", d1vars))] 

    setcolorder(D, c(byvars, d1vars, setdiff(d2vars, d1vars))) 
    setorderv(D, byvars)[] 
} 

g(site1, site2, "id") 

這給

id A B C d 
1: 1 i E NA 4 
2: 2 g F NA 4 
3: 3 h NA 4 1 
4: 4 NA B 4 2 
5: 5 j G NA NA 
6: 6 c NA 3 4 
7: 7 a D 2 NA 
8: 8 b NA 2 NA 
9: 9 d G 1 4 
10: 10 f NA 1 NA 
11: 12 NA V NA 2 
12: 13 n J NA 1 
13: 14 NA T NA 1 
14: 15 NA X NA 1 

它是如何工作

byvars參數允許列名的向量。

相當新的..語法允許引用存儲在data.table外部的列的索引。我查看了FAQ和?data.table,並且找不到任何文檔。目前,它是the first changelog item in 1.10.2 at least

要給出「站點1在站點2上的層次結構」,我們首先從站點2添加站點1,然後添加站點1,以便獲取最後的編輯。

funion的使用假設每個表格中沒有重複。如果有,將需要該步驟更復雜的方法,大概就像

D = rbind(d1[, ..byvars], d2[,..byvars][!d1, on=byvars]) 
+0

(我不明白col.smash參考,也沒有關於此事的功能,所以不能真正評論它爲什麼不起作用。) – Frank

+0

@akrun是的,有fsetdiff。你認爲它在哪裏適合?我正在考慮如何使用它,但隨後開始使用funion。 – Frank

+0

這是一個廢話粉碎的參考。但感謝這一點。爲什麼在byvars之前有一個'..'?我不太明白, – akash87