2013-04-10 42 views
13

我剛在腳本中發現了這個警告,這有點奇怪。rbindlist兩個data.tables,其中一個有因子,另一個有字符類型的列

# Warning message: 
# In rbindlist(list(DT.1, DT.2)) : NAs introduced by coercion 

觀察1:這裏有一個重複的例子:

require(data.table) 
DT.1 <- data.table(x = letters[1:5], y = 6:10) 
DT.2 <- data.table(x = LETTERS[1:5], y = 11:15) 

# works fine 
rbindlist(list(DT.1, DT.2)) 
#  x y 
# 1: a 6 
# 2: b 7 
# 3: c 8 
# 4: d 9 
# 5: e 10 
# 6: A 11 
# 7: B 12 
# 8: C 13 
# 9: D 14 
# 10: E 15 

不過,現在如果我將列xfactor(有序與否),做同樣的:

DT.1[, x := factor(x)] 
rbindlist(list(DT.1, DT.2)) 
#  x y 
# 1: a 6 
# 2: b 7 
# 3: c 8 
# 4: d 9 
# 5: e 10 
# 6: NA 11 
# 7: NA 12 
# 8: NA 13 
# 9: NA 14 
# 10: NA 15 
# Warning message: 
# In rbindlist(list(DT.1, DT.2)) : NAs introduced by coercion 

但是rbind很好地完成這項工作!

rbind(DT.1, DT.2) # where DT.1 has column x as factor 
# do.call(rbind, list(DT.1, DT.2)) # also works fine 
#  x y 
# 1: a 6 
# 2: b 7 
# 3: c 8 
# 4: d 9 
# 5: e 10 
# 6: A 11 
# 7: B 12 
# 8: C 13 
# 9: D 14 
# 10: E 15 

相同的行爲可以如果柱xordered factor以及被再現。由於幫助頁?rbindlist說:Same as do.call("rbind",l), but much faster.,我猜這不是所需的行爲?


這裏是我的會話信息:

# R version 3.0.0 (2013-04-03) 
# Platform: x86_64-apple-darwin10.8.0 (64-bit) 
# 
# locale: 
# [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8 
# 
# attached base packages: 
# [1] stats  graphics grDevices utils  datasets methods base  
# 
# other attached packages: 
# [1] data.table_1.8.8 
# 
# loaded via a namespace (and not attached): 
# [1] tools_3.0.0 

編輯:

觀察2:繼@ AnandaMahto是另一個有趣的現象,反向排序:

# column x in DT.1 is still a factor 
rbindlist(list(DT.2, DT.1)) 
#  x y 
# 1: A 11 
# 2: B 12 
# 3: C 13 
# 4: D 14 
# 5: E 15 
# 6: 1 6 
# 7: 2 7 
# 8: 3 8 
# 9: 4 9 
# 10: 5 10 

這裏,從DT.1列被無聲地強制爲numeric
編輯:只是爲了澄清,這是與rbind(DT2, DT1)相同的行爲,DT1的列x是一個因素。 rbind似乎保留了第一個參數的類。我將在這裏留下這部分內容,並提及在這種情況下,這是所需的行爲,因爲rbindlistrbind的更快實施。

觀察3:如果現在,這兩個列被轉換爲因素:

# DT.1 column x is already a factor 
DT.2[, x := factor(x)] 
rbindlist(list(DT.1, DT.2)) 
#  x y 
# 1: a 6 
# 2: b 7 
# 3: c 8 
# 4: d 9 
# 5: e 10 
# 6: a 11 
# 7: b 12 
# 8: c 13 
# 9: d 14 
# 10: e 15 

在此,柱xDT.2丟失(/與的DT.1取代)。如果訂單逆轉,則會發生完全相反的情況(DT.1的第x列被替換爲DT.2的第x列)。

一般來說,在rbindlist中處理factor列似乎存在問題。

回答

7

更新 - 這個bug(#2650)在V1.8 2013年5月固定在17。9


相信rbindlist當施加到因素是相結合的因子的數值,並使用僅與所述第一列表元素相關聯的水平。

在本bug報告: http://r-forge.r-project.org/tracker/index.php?func=detail&aid=2650&group_id=240&atid=975


# Temporary workaround: 

levs <- c(as.character(DT.1$x), as.character(DT.2$x)) 

DT.1[, x := factor(x, levels=levs)] 
DT.2[, x := factor(x, levels=levs)] 

rbindlist(list(DT.1, DT.2)) 

截至怎麼回事另一種觀點認爲:

DT3 <- data.table(x=c("1st", "2nd"), y=1:2) 
DT4 <- copy(DT3) 

DT3[, x := factor(x, levels=x)] 
DT4[, x := factor(x, levels=x, labels=rev(x))] 

DT3 
DT4 

# Have a look at the difference: 
rbindlist(list(DT3, DT4))$x 
# [1] 1st 2nd 1st 2nd 
# Levels: 1st 2nd 

do.call(rbind, list(DT3, DT4))$x 
# [1] 1st 2nd 2nd 1st 
# Levels: 1st 2nd 

編輯按評論:

爲觀察1,發生的事情類似:

x <- factor(LETTERS[1:5]) 

x[6:10] <- letters[1:5] 
x 

# Notice however, if you are assigning a value that is already present 
x[11] <- "S" # warning, since `S` is not one of the levels of x 
x[12] <- "D" # all good, since `D` *is* one of the levels of x 
+0

裏卡多,太棒了!感謝提交錯誤。我認爲你解釋的是正確的,但是這個故事的一部分。如在「觀察1」中那樣,沒有數值被組合。我的意思是說,他們的行爲有所不同,具體取決於兩列是否都是因素,也取決於你綁定它們的順序。那個聽起來是對的嗎? – Arun 2013-04-10 20:35:25

+0

(+1)感謝您的臨時解決方法。考慮到使用「因素」執行的操作的次數,我希望這個錯誤的優先次序碰撞......(我會等待一會兒,然後再接受答案)。 – Arun 2013-04-10 20:38:41

+0

@Arun,請參閱上面的編輯以回答關於觀察的問題1 – 2013-04-10 20:46:16

2

rbindlist是超快的,因爲它不會做的rbindfilldo.call(rbind.data.frame,...)

檢查您可以使用一種變通方法這樣保證因素被強制爲人物。

DT.1 <- data.table(x = factor(letters[1:5]), y = 6:10) 
DT.2 <- data.table(x = LETTERS[1:5], y = 11:15) 


for(ii in seq_along(DDL)){ 
    ff <- Filter(function(x) is.factor(DDL[[ii]][[x]]), names(DDL[[ii]])) 
    for(fn in ff){ 
    set(DDL[[ii]], j = fn, value = as.character(DDL[[ii]][[fn]])) 
    } 
    } 
rbindlist(DDL) 

或(有效的內存更少)

rbindlist(rapply(DDL, classes = 'factor', f= as.character, how = 'replace')) 
相關問題