data.table在每列上应用函数

时间:2018-08-28 08:22:46

标签: r loops set data.table lapply

我想我已经很接近解决方案了,但是我很难将lapply与data.table结合起来。我阅读了很多有关lapply的内容,并找到了有关data.table的示例,但是这种思维方式对我来说是新的,它使我发疯...

这是我的数据表。

cells <- c(150, 1,1980,1,1,1,0,0,0,1,2004,3,
       99 , 1,1980,1,1,1,1,0,0,0,2004,4,
       899, 1,1980,0,1,0,1,1,1,1,2007,4,
       789, 1,1982,1,1,1,0,1,1,1,2004,3 )
colname <- c("number","sex", "birthy", "2004","2005", "2006", "2007", "2008", "2009","2010","begy","SeqLen")
rowname <- c("2","3","4","5")
y <- matrix(cells, nrow=4, ncol=12, byrow=TRUE, dimnames = list(rowname,colname))
y <- data.table(y, keep.rownames = TRUE)

我想逐步浏览列名的向量

cols <- c(paste(2004:2010, sep=" "))

仅对一列执行以下操作即可!

vec <- "2005"
y[,  (vec) := ifelse((vec) < as.numeric(begy),0, ifelse( ((vec) > as.numeric(begy) + as.numeric(SeqLen) -1) ,0,1)) ]

创建一个函数并逐步遍历向量接缝是一个很好的解决方案,但是如何呢? 我找到了...

dt[ , (cols) := lapply(.SD, "*", -1), .SDcols = cols]

但是在这个示例中我可以将ifelse放在哪里?

我还读到了有关for循环和set函数的信息,

for (j in cols) set(dt, j = j, value = ifelse((dt[[j]]) < as.numeric(dt[[begy]]),0, ifelse( (dt[[j]] > as.numeric(dt[[begy]]) + as.numeric(dt[[SeqLen]]) -1) ,0,1)))

但这是废话。

谢谢 阿丽娜

1 个答案:

答案 0 :(得分:1)

如果每一行的年份列在begybegy + SeqLen - 1之间,则好像您将年份列设置为1。这是执行此操作的另一种方法:

y[order(rn), 
    (grep("^20", names(y), value=TRUE)) := 
        dcast(y[, seq(begy, by=1, length.out=SeqLen), by=.(rn)], rn ~ V1, length)[,-1L]]
y

输出:

   rn number sex birthy 2004 2005 2006 2007 2008 2009 2010 begy SeqLen
1:  2    150   1   1980    1    1    1    0    0    0    0 2004      3
2:  3     99   1   1980    1    1    1    1    0    0    0 2004      4
3:  4    899   1   1980    0    0    0    1    1    1    1 2007      4
4:  5    789   1   1982    1    1    1    0    0    0    0 2004      3

说明:

为每一行创建一个年份序列,然后使用dcast进行一次热编码。使用输出覆盖年份列。

order(rn)将确保我们不会在dcast之后错误地覆盖行


弗兰克的方法更快:

y[, as.character(2004:2010) := 
    lapply(2004:2010, function(x) as.integer(between(x, begy, begy + SeqLen - 1)))]