从三列data.table[R]中按名称将所有因子级别作为新列返回
有没有办法使用data.table或dplyr来解决以下问题从三列data.table[R]中按名称将所有因子级别作为新列返回,r,data.table,dplyr,R,Data.table,Dplyr,有没有办法使用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
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
这类似于
仅使用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
df1带基数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))))
命名可能不是命名任何东西的好方法,因为我们一直都在使用这个函数。无论如何,您的解决方案工作效率很高!如果您最终希望a
的每个值都有一行,请使用包中的spread(DT,c,b)
。dcast(DT[,I:=.I],a+I~c,value.var=“b”)
回答得好@Frank!能够稍微修改以删除b和c列:DT[,(uc):=lapply(uc,函数(x)ifelse(c==x,b,NA))[,!c(“b”,“c”),with=FALSE]
@BobHopez谢谢:)我忘记删除b,但现在已经添加了它。如果您通过设置为NULL
以引用方式删除(如答案中所示),则可以从DT
中删除b
和c
,而无需创建新表。相反,如果你用=FALSE做with
的事情,你需要像newDT那样分配它,不能让你的底层代码块@Frank工作。上半部分工作得很好。运行for loop后获得的j是-2147483648,超出范围[1,ncol=5]。嗯,如果您删除DT
,按照您的问题重新创建它,然后运行下半部分,它不工作吗?几乎就在那里了。。。将列名更改为paste0(“c”,名称)。是的,model.matrix会这样做(将变量名与级别组合)。我将名称更改为原始因子级别
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
names <- unique(as.character(DT$c))
cbind(a = DT$a, as.data.frame(sapply(names, function(x) ifelse(DT$c==x, DT$b, NA))))