【问题标题】:Can I programmatically update the type of a set of columns (to factors) in data.table?我可以以编程方式更新 data.table 中一组列的类型(到因子)吗?
【发布时间】:2014-12-05 14:35:19
【问题描述】:

我想将 data.table 中的一组列修改为因子。如果我事先知道列的名称,我想这会很简单。

library(data.table)
dt1  <- data.table(a = (1:4), b = rep(c('a','b')), c = rep(c(0,1)))
dt1[,class(b)]
dt1[,b:=factor(b)]
dt1[,class(b)]

但我没有,而是有一个变量名列表

vars.factors  <- c('b','c')

我可以毫无问题地将因子函数应用于它们......

lapply(vars.factors, function(x) dt1[,class(get(x))])
lapply(vars.factors, function(x) dt1[,factor(get(x))])
lapply(vars.factors, function(x) dt1[,factor(get(x))])

但我不知道如何重新分配或更新数据表中的原始列。

这失败了……

  lapply(vars.factors, function(x) dt1[,x:=factor(get(x))])
  # Error in get(x) : invalid first argument 

这样...

  lapply(vars.factors, function(x) dt1[,get(x):=factor(get(x))])
  # Error in get(x) : object 'b' not found 

注意。我尝试了here 提出的答案,但没有任何运气。

【问题讨论】:

标签: r data.table r-factor


【解决方案1】:

是的,这很简单:

dt1[, (vars.factors) := lapply(.SD, as.factor), .SDcols=vars.factors]

LHSj 中的:=)中,我们指定了列的名称。如果一个列已经存在,它将被更新,否则,将创建一个新列。在 RHS 中,我们循环遍历 .SD 中的所有列(代表 Data 的 Subset),并指定应该在 @987654325 中的列@ 带有 .SDcols 参数。

跟进评论:

请注意,我们需要用 () 包裹 LHS 以对其进行求值 并获取 vars.factors 变量中的列名。这是因为我们允许语法

DT[, col := value]

当只有一列要分配时,通过将列名指定为符号(不带引号),纯粹是为了方便。这将创建一个名为 col 的列并将 value 分配给它。

为了区分这两种情况,我们需要()。用() 包裹它就足以表明我们确实需要获取变量中的值。

【讨论】:

  • 谢谢你 - 这行得通。我之前尝试过这个dt1[, vars.factors := lapply(.SD, function(x) factor(x)), .SDcols=vars.factors],但它似乎做了一些非常不同的事情。有没有机会解释一下原因?
  • 感谢您的补充说明
【解决方案2】:

使用数据框:

> df1 = data.frame(dt1)
> df1[,vars.factors] = data.frame(sapply(df1[,vars.factors], factor))
> dt1 = data.table(df1)

> dt1
   a b c
1: 1 1 b
2: 2 2 c
3: 3 3 b
4: 4 4 c

> str(dt1)
Classes ‘data.table’ and 'data.frame':  4 obs. of  3 variables:
 $ a: int  1 2 3 4
 $ b: Factor w/ 4 levels "1","2","3","4": 1 2 3 4
 $ c: Factor w/ 2 levels "b","c": 1 2 1 2
 - attr(*, ".internal.selfref")=<externalptr> 

【讨论】:

  • 这个想法很好,但这不是这样做的方法。这里不需要data.frame 两次。您可以在一行中完成所有操作,例如 dt1[vars.factors] &lt;- lapply(setDF(dt1)[vars.factors], factor) ; setDT(dt1)
  • @DavidArenburg:您的解决方案很优雅。我使用最少的函数来获得解决方案。
【解决方案3】:

还可以

for (col in vars.factors) 
  set(dt, j=col, value=as.factor(dt1[[col]]))

vars.factors 可以是整数向量或指定要修改的列的字符名称。

请参阅https://stackoverflow.com/a/33000778/4241780 了解更多信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-06
    • 2021-03-05
    • 1970-01-01
    • 1970-01-01
    • 2012-03-18
    相关资源
    最近更新 更多