我將給出很多嚴格意義上不需要的背景(我歡迎大家提出改進意見),如果你只想看到我的主要問題,你可以滾動到最后。
背景
我有一個資料集,我想根據一些規則來填補幾個變數的缺失值。一些示例資料:library(data.table)
library(tidyverse)
dt <- data. frame(id = c('a/span>。 'a'。 'a'/span>, 'a'/span>。 'a',
'b', 'b',。 'b', 'b'),
var1 = c(1。 1。 NA, 1, NA, NA
NA, 5,。 NA, 5),
var2 = c('hi'。 'hi'。 NA, 'hi'。 'hi',
'bye', NA, '再見'。 'bye', NA), ,
年 = c(2005。 2009,
1995。 1998, 2002))
請注意,真實的資料是很大的:1000萬個觀察值,至少有30-40個變數,我將填寫10個左右的列,因此采用data.table的方法。
我目前使用一個函式來填充它們,該函式可以找到領先和滯后,并檢查我的條件,就像這樣:
fill. in < - function(var, yr, finyr) {
leadv <- lead(var, order_by = yr)
lagv <- lag(var, order_by = yr)
leadyr <- lead(yr, order_by = yr)
lagyr <- lag(yr, order_by = yr)
# ------- build the updated var w/ sequential conditions。
# keep the var as it is if not missing >。
try1 <- ifelse(test = ! is.na(var),
是 = var,
no = NA)
# 如果領先和落后匹配,并且沒有超過2年的遺漏,則填寫。
try2 <- ifelse(test = is. na(try1) & leadv == lagv &
abs(leadyr-lagyr) < = 3 &
!is.na(leadv),
是 = leadv,
no = try1)
# 如果是最后一年的觀察資料,就填上滯后期。
ifelse(test = is. na(try2) & yr == finyr&
abs(yr-lagyr) < = 3 & ! is.na(lagv),
是 = lagv,
no = try2)
}
我使用data.table的.SD呼叫這個:
setDT(dt)
dt[, finalyr 。 = max(年)。 by = id]
# 要迭代的變數和新的列名。
fill.in. vs < - c('var1'/span>。 'var2')
fixed.vnames <- paste0('fixed.', fill.in.vs)
# I don't want factor values, so make strings characters
dt$var2 <- as. character(dt$var2)
dt[, (fixed. vnames) := sapply(.SD,
FUN = fill.in,.
yr = year,
finyr = finalyr,
simplify = FALSE, USE. NAMES = FALSE),。
通過= id, .SDcols = fill.in.vs]
這就得到了我想要的資料:
這就得到了我想要的資料。
id var1 var2 year finalyr fixed.var1 fixed.var2
1: a 1 hi 2005 2009 1 hi
2: a 1 hi 2006 2009 1 hi
3: a NA <NA> 2007 2009 1 hi
4: a 1 hi 2008 2009 1 hi
5: a NA hi 2009 2009 1 hi
6: b NA bye 1995 2002 NA bye
7: b 5 <NA> 1996 2002 5 bye
8: b 5 拜拜 1997 2002 5拜拜
9: b NA bye 1998 2002 NA bye
10: b 5 <NA> 2002 2002 5 <NA>
主要問題
好了,現在是我的實際問題。我想要一個已經被更新的行的指示器。我認為我的更新方式,即使用data.table和.SD,不允許產生成對的變數(我的意思是在每個迭代中產生兩個或三個不同的變數),所以我想我只是標記那些本質上original.var != fixed.var的觀察結果。
這就遇到了問題,因為R不喜歡將數值與NAs進行比較。(見這里的例子。)
我曾試圖實作一些解決方案,但在試圖對一個變數串列進行操作時,我一直遇到問題。例如,下面的方法可以識別哪些是相同的或不相同的:
# this works:
dt$updated。 var1 < - mapply(identical, dt$var1, dt$fixed。 var1,
SIMPLIFY = FALSE, USE. NAMES = FALSE)。
dt[。 c('var1', ' fixed. var1', 'uped.var1')]
var1 fixed.var1 updated.var1
1: 1 1 TRUE
2: 1 1 TRUE
3: NA 1 FALSE
4: 1 1 TRUE
5: NA 1 FALSE
6: NA NA TRUE
7: 5 5 TRUE
8: 5 5 TRUE
9: NA NA TRUE
10: 5 5 TRUE
但是當我試圖用data.table和變數串列來使用它時,它對兩個變數都回傳FALSE:
# indicate updated observations。
update.names <- paste0('uped.', fill.in.vs)
# this doesn't work how I want it to:
dt[, (update. names) := mapply(identical,.
.SD,.
fixed.vnames,。
SIMPLIFY = FALSE, USE. NAMES = FALSE),.
.SDcols = fill.in.vs]
dt[。 c('var1', ' fixed. var1', 'uped.var1')]
var1 fixed.var1 updated.var1
1: 1 1 FALSE
2: 1 1 FALSE
3: NA 1 FALSE
4: 1 1 FALSE
5: NA 1 FALSE
6: NA NA FALSE
7: 5 5 FALSE
8: 5 5 FALSE
9: NA NA FALSE
10: 5 5 FALSE
我不確定問題出在哪里,但我猜測它與我試圖讓mapply識別 "固定 "變數的串列作為變數進行迭代有關。
如果有任何建議,我們將不勝感激。
uj5u.com熱心網友回復:
你可以寫一個自定義函式來處理這個問題,并使用Map來為每一對應用函式。
library(data.table)
new_cols < - function(x, y) {>
z <- x != y | 是。 na(x) & is。 na(y)
z[是。 na(z)] <- TRUE
z
}
update.names <- paste0('uped.', fill.in.vs)
dt[, (update。 names) 。 = Map(new_cols, dt[, . .fixed.vnames], dt[, 。 .fill.in.vs])]
dt
# id var1 var2 year finalyr fixed.var1 fixed.var2 updated.var1 updated.var2
# 1: a 1 hi 2005 2009 1 hi FALSE FALSE
# 2: a 1 hi 2006 2009 1 hi FALSE FALSE
# 3: a NA <NA> 2007 2009 1 hi TRUE TRUE。
# 4: a 1 hi 2008 2009 1 hi FALSE FALSE
# 5: a NA hi 2009 2009 1 hi TRUE FALSE
# 6: b NA bye 1995 2002 NA bye TRUE FALSE
# 7: b 5 <NA> 1996 2002 5 bye FALSE TRUE。
# 8: b 5 bye 1997 2002 5 bye FALSE FALSE
# 9: b NA bye 1998 2002 NA bye TRUE FALSE
#10: b 5 <NA> 2002 2002 5 <NA> FALSE TRUE。
你可能會在控制臺得到警告,請暫時忽略它們。有一個關于它的開放性問題。https://github.com/Rdatatable/data.table/issues/2988
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/326663.html
標籤:
