【问题标题】:Return all factor levels by name as new columns from a three column data.table [R]从三列 data.table [R] 中按名称返回所有因子水平作为新列
【发布时间】:2015-07-15 20:40:53
【问题描述】:

有什么方法可以使用 data.table 或 dplyr 来解决以下问题?

library(data.table)

(DT = data.table(a = LETTERS[c(1, 1:3, 8)], b = c(2, 4:7), 
                 c = as.factor(c("bob", "mary", "bob", "george", "alice")), key="a"))

返回:

#    a b      c
# 1: A 2    bob
# 2: A 4   mary
# 3: B 5    bob
# 4: C 6 george
# 5: H 7  alice

想要得到这个:

#        alice bob george  mary 
# 1: A    NA   2    NA     NA
# 2: A    NA   NA   NA     4
# 3: B    NA   5    NA     NA
# 4: C    NA   NA   6      NA
# 5: H    7    NA   NA     NA

【问题讨论】:

  • 命名任何东西c 可能不是一个好习惯,因为我们一直都在使用这个函数。
  • 好点。无论如何,您的解决方案都能高效运行!
  • 如果您最终希望a 的每个值都有一行,请使用tidyr 包中的spread(DT, c, b)
  • dcast(DT[, I := .I], a + I ~ c, value.var="b")

标签: r data.table dplyr


【解决方案1】:

这类似于creating dummy variables

uc <- sort(unique(as.character(DT$c)))
DT[,(uc):=lapply(uc,function(x)ifelse(c==x,b,NA))][,c('b','c'):=NULL]

我听说过关于ifelse 的坏消息,所以可能是更快的路线

uc <- sort(unique(as.character(DT$c)))
is <- 1:nrow(DT)
js <- as.character(DT$c)
vs <- DT$b

DT[,(uc):=NA_integer_]
for (i in is) set(DT,i=is[i],j=js[i],value=vs[i])

DT[,c('b','c'):=NULL]

【讨论】:

  • 好答案@Frank!能够稍微修改以删除 bc 列:DT[,(uc):=lapply(uc, function(x)ifelse(c==x, b, NA))][, !c("b", "c"), with=FALSE]
  • @BobHopez 谢谢 :) 我忘了删除 b,但现在已经添加了。如果您通过设置为NULL 通过引用(如答案)删除,则可以从DT 中消除bc,并且不需要创建新表。相反,如果您执行with=FALSE 的操作,则需要像newDT &lt;- DT[...][...,with=FALSE] 一样分配它以进一步使用结果,制作副本(花费时间和内存)。
  • 无法让您的底部代码块工作@Frank。上半部分完美运行。
  • 运行 for 循环后得到 j 为 -2147483648,超出范围 [1,ncol=5]
  • 嗯,如果你删除DT,按照你的问题重新创建它,然后运行底部块,它不起作用吗?
【解决方案2】:

仅使用 Frank 的虚拟变量的想法:

df1 <- cbind( a = DT$a, as.data.frame( model.matrix(a ~ c - 1, data = DT ) * DT$b ))
df1[df1==0] <- NA
names(df1) <- c("a", levels(DT$c))

#   a alice bob george mary
# 1 A    NA   2     NA   NA
# 2 A    NA  NA     NA    4
# 3 B    NA   5     NA   NA
# 4 C    NA  NA      6   NA
# 5 H     7  NA     NA   NA

【讨论】:

  • 差不多了...将列名更改为 paste0("c", names)
  • 是的,model.matrix 就是这样做的(将变量名称与级别相结合)。我将名称更改为原始因子水平。
【解决方案3】:

使用基础 R:

names <- unique(as.character(DT$c))
cbind(a = DT$a, as.data.frame(sapply(names, function(x) ifelse(DT$c==x, DT$b, NA))))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    相关资源
    最近更新 更多