【发布时间】:2021-02-11 20:31:06
【问题描述】:
在 R(dplyr、data.table 等)中如何去:
group var
a 0
a 0
a 1
a 0
b 1
b 1
b 0
c 1
c 0
c 1
c 1
到:
最好是动态的,例如使用可变数量的组。
【问题讨论】:
标签: r dplyr data.table
在 R(dplyr、data.table 等)中如何去:
group var
a 0
a 0
a 1
a 0
b 1
b 1
b 0
c 1
c 0
c 1
c 1
到:
最好是动态的,例如使用可变数量的组。
【问题讨论】:
标签: r dplyr data.table
你可以这样做:
d <- data.frame(group=sample(LETTERS[1:4],100,TRUE), var = rnorm(100))
groupInds <- split(1:NROW(d),d$group)
newColumns <- do.call("cbind",lapply(1:length(groupInds), function(k) {
newColValues <- rep(NA,NROW(d)) #some init, you left blank, so I thought of NAs
inds <- groupInds[[k]]
newColValues[inds] <- d$var[inds]
data.frame(newColValues)
}))
names(newColumns) <- paste0(names(groupInds),"_var")
newdf <- cbind(d,newColumns)
它在基础 R 中的所有内容。如果您知道可以使用矩阵,则可以将强制转换为 data.frame,因为性能原因,而不是重置 names,而是使用 colnames。
【讨论】:
我们可以通过'group'拆分后使用bdiag
library(Matrix)
m1 <- as.matrix(bdiag(split(df1$var, df1$group)))
colnames(m1) <- paste0(unique(df1$group), "_var")
cbind(df1, m1)
-输出
# group var a_var b_var c_var
#1 a 0 0 0 0
#2 a 0 0 0 0
#3 a 1 1 0 0
#4 a 0 0 0 0
#5 b 1 0 1 0
#6 b 1 0 1 0
#7 b 0 0 0 0
#8 c 1 0 0 1
#9 c 0 0 0 0
#10 c 1 0 0 1
#11 c 1 0 0 1
为了将值“0”与稀缺矩阵中创建的值区分开来,我们可以做一些replacement
m1 <- as.matrix(bdiag(split(na_if(df1$var, 0), df1$group)))
i1 <- is.na(m1)
i2 <- m1 == 0 & !is.na(m1)
m1[i1] <- 0
m1[i2] <- NA
colnames(m1) <- paste0(unique(df1$group), "_var")
cbind(df1, m1)
# group var a_var b_var c_var
#1 a 0 0 NA NA
#2 a 0 0 NA NA
#3 a 1 1 NA NA
#4 a 0 0 NA NA
#5 b 1 NA 1 NA
#6 b 1 NA 1 NA
#7 b 0 NA 0 NA
#8 c 1 NA NA 1
#9 c 0 NA NA 0
#10 c 1 NA NA 1
#11 c 1 NA NA 1
或者这可以使用tidyverse 来完成,方法是将数据拆分为带有group 列的data.frame 的list,然后重命名“var”列并使用bind_rows,这将自动添加NA如果在list 元素中找不到该列,则元素
library(dplyr)
library(purrr)
library(stringr)
df1 %>%
group_split(group) %>%
map(~ .x %>%
rename(!! str_c(first(.x$group), '_var') := var) %>%
select(-group)) %>%
bind_rows %>%
bind_cols(df1, .)
-输出
# group var a_var b_var c_var
#1 a 0 0 NA NA
#2 a 0 0 NA NA
#3 a 1 1 NA NA
#4 a 0 0 NA NA
#5 b 1 NA 1 NA
#6 b 1 NA 1 NA
#7 b 0 NA 0 NA
#8 c 1 NA NA 1
#9 c 0 NA NA 0
#10 c 1 NA NA 1
#11 c 1 NA NA 1
df1 <- structure(list(group = c("a", "a", "a", "a", "b", "b", "b", "c",
"c", "c", "c"), var = c(0L, 0L, 1L, 0L, 1L, 1L, 0L, 1L, 0L, 1L,
1L)), class = "data.frame", row.names = c(NA, -11L))
【讨论】:
这是“data.table”的替代方案:
library(data.table)
cbind(df1, as.data.table(df1)[
, dcast(.SD, .I ~ paste0(group, "_var"), value.var = "var")][
, ".I" := NULL])
# group var a_var b_var c_var
# 1 a 0 0 NA NA
# 2 a 0 0 NA NA
# 3 a 1 1 NA NA
# 4 a 0 0 NA NA
# 5 b 1 NA 1 NA
# 6 b 1 NA 1 NA
# 7 b 0 NA 0 NA
# 8 c 1 NA NA 1
# 9 c 0 NA NA 0
# 10 c 1 NA NA 1
# 11 c 1 NA NA 1
【讨论】: