我想根据“lead”变量分隔变量。 x3在以下情况中:
set.seed(2)
df = data.frame(x1 = sample(4), x2 = sample(4), x3 = sample(letters[1:2], size = 4, replace = TRUE))
df
# x1 x2 x3
# 1 1 4 a
# 2 3 3 b
# 3 2 1 b
# 4 4 2 a
# Desired output
# x3 x1.a x2.a x1.b x2.b
# a 1 4 NA NA
# b NA NA 3 3
# b NA NA 2 1
# a 4 2 NA NA
我知道这可以通过reshape2::dcast()
实现,但我只能让它适用于两个变量:
reshape2::dcast(df[,2:3], seq_along(x3) ~ x3, value.var = "x2")[, -1]
# a b
# 1 2 NA
# 2 NA 1
# 3 NA 3
# 4 4 NA
但可能这只是对dcast
的完全滥用。是否有一个优雅的解决方案,没有拆分和合并df
?
编辑:有些人提到这样做是一个可怕的想法,我可能不应该做这样的事情。让我详细说明何时可以理解。
想象一下x3
是特定算法的开关。在这种情况下,a
和b
是选项。此外,x1
和x2
是算法可以采用的参数。遗憾的是,这两种算法在x1
和x2
的相同参数设置上的行为确实不同,因此将它们作为不同的功能处理以将其无关性考虑在内是有意义的。
答案 0 :(得分:5)
这是使用X3
创建虚拟交互项的解决方案。可能可以使用dplyr
或data.table
将所有这些代码整合到一行中,但这里是:
temp <- model.matrix( ~ (x1+x2):x3-1, df)
temp[model.matrix( ~ (I(x1+1)+I(x2+1)):x3-1, df) == temp] <- NA
data.frame(df$x3, temp)
#### df.x3 x1.x3a x1.x3b x3a.x2 x3b.x2
#### a 1 NA 4 NA
#### b NA 3 NA 3
#### b NA 2 NA 1
#### a 4 NA 2 NA
列的最终名称和顺序与您略有不同。
注意 :(第二行代码的目的)。
model.matrix 函数会创建零而不是NAs
,因此无法区分预先存在的零。第二行是仅查找最终NAs的技巧(它通过创建第二个模型矩阵,同时通过+1
更改其值来工作)。
答案 1 :(得分:3)
如果您再添加一列并执行中介melt
,则可以使用dcast
和melt
来实现此目的。
library(reshape2)
library(magrittr)
set.seed(2)
df = data.frame(x1 = sample(4), x2 = sample(4), x3 = sample(letters[1:2], size = 4, replace = TRUE))
df$row <- 1:nrow(df)
melt(df,
id.vars = c("row", "x3"),
measure.vars = c("x1", "x2")) %>%
dcast(row ~ x3 + variable,
value.var = "value")
然而,它比agenis的解决方案慢了2-3倍,即使我将数据框的大小推高到10,000行也是如此。 (8对16毫秒)。
答案 2 :(得分:2)
我自己提出的一个基本解决方案:
cat.var = "x3"
cont.vars = setdiff(colnames(df), cat.var)
categories = unique(df[[cat.var]])
res = lapply(categories, function(x) {
this.df = df[, cont.vars, drop = FALSE]
this.df[df[[cat.var]] != x,] = NA
setNames(this.df, paste0(x,".",colnames(this.df)))
})
res = do.call(cbind, c(list(df[, cat.var, drop=FALSE]), res))
res
# x3 a.x1 a.x2 b.x1 b.x2
# 1 a 1 4 NA NA
# 2 b NA NA 3 3
# 3 b NA NA 2 1
# 4 a 4 2 NA NA
答案 3 :(得分:1)
您可以使用tidyr
library(tidyr);library(dplyr)
df <- df %>% mutate(rows=rownames(.)) %>%
gather(., key="vars", value= "val", -x3,-rows) %>%
mutate(vars= paste(x3,vars, sep=".")) %>%
spread(., key = vars, value = val) %>%
select(-rows)
它将数据集收集为长格式,然后将x3变量分开,然后在创建所需的变量标题后再次传播数据。