我有一个这样的数据框:
df <- data.frame(v11=rnorm(1), v12=rnorm(1), v21=rnorm(1), v31=rnorm(1), v41=rnorm(1), v42=rnorm(1), v43=rnorm(1))
此数据框只有一行
df
# v11 v12 v21 v31 v41 v42 v43
# 1 -0.4425873 0.6062714 -0.3816921 0.2477926 0.1292103 0.2801346 0.4290997
某些列是针对同一主题的重复观察,例如v11
和v12
是来自同一主题的两个观察结果。
v21
和v32
只是单一观察。 v4x
有三个观察结果。
我想重塑数据框,如下所示:
v11 v21 v31 v41
v12 NA NA v42
NA NA NA v43
请注意,它应包含变量的值而不是其名称。
我有一个指示器向量,用于标记哪个观察结果:
v <- c(1, 2, 1, 1, 1, 2, 3)
每个&#34; 1&#34;标志着新专栏的开始。
我的第一个想法是自己构建每一行:
row1 <- df[, v == 1]
row2 <- df[, v == 2]
row3 <- df[, v == 3]
但这不包含NA。 必须有一个更简单的方法。
注意:解决方案不应该依赖于原始列名v11
,v41
等,而只能依赖于向量v
。< / p>
答案 0 :(得分:2)
以下是dplyr
+ tidyr
的解决方案:
library(dplyr)
library(tidyr)
v <- c(1,2,1,1,1,2,3)
df %>%
gather(var, value) %>%
mutate(row_num = v,
col_num = paste0("v", cumsum(v==1))) %>%
select(-var) %>%
spread(col_num, value)
<强>结果:强>
row_num v1 v2 v3 v4
1 1 -0.5604756 1.558708 0.07050839 0.1292877
2 2 -0.2301775 NA NA 1.7150650
3 3 NA NA NA 0.4609162
数据:强>
df = structure(list(v11 = -0.560475646552213, v12 = -0.23017748948328,
v21 = 1.55870831414912, v32 = 0.070508391424576, v41 = 0.129287735160946,
v42 = 1.71506498688328, v43 = 0.460916205989202), .Names = c("v11",
"v12", "v21", "v32", "v41", "v42", "v43"), row.names = c(NA,
-1L), class = "data.frame")
答案 1 :(得分:0)
您也可以使用melt
和dcast
以及reshape2
{/ 1}}中的transform
和library(reshape2)
dcast(transform(melt(df),
rownum = substr(variable,3,3),
cols = substr(variable,1,2)),
rownum ~ cols, value.var = 'value')
执行此操作:
rownum v1 v2 v3 v4
1 1 1.43420148 0.7391372 -1.758605 -0.06982523
2 2 -0.07729196 NA NA 0.45190553
3 3 NA NA NA -1.95836646
结果:
set.seed(2017)
df <- data.frame(v11=rnorm(1), v12=rnorm(1), v21=rnorm(1), v31=rnorm(1), v41=rnorm(1), v42=rnorm(1), v43=rnorm(1))
数据:
selected
答案 2 :(得分:0)
这是基础R
的解决方案,仅取决于对测量数据进行分组的向量v
:
首先,示例数据:
set.seed(0)
df <- data.frame(v11=rnorm(1), v12=rnorm(1), v21=rnorm(1), v31=rnorm(1), v41=rnorm(1), v42=rnorm(1), v43=rnorm(1))
# v11 v12 v21 v31 v41 v42 v43
#1 1.262954 -0.3262334 1.329799 1.272429 0.4146414 -1.53995 -0.928567
v <- c(1,2,1,1,1,2,3)
然后做:
v_grp <- cumsum(v == 1) # create index that groups the measurement data
out <- split(unlist(df), v_grp) # split vector of measurements by group
## following required to pad split vectors with `NA`.
## There are packages that give functions that do this
max_in_group <- max(summary(factor(v_grp)))
out <- lapply(out, function(v) {
num_in_vec <- length(v)
if (num_in_vec < max_in_group) {
v <- c(v, rep(NA, max_in_group - num_in_vec))
}
return(unname(v))
})
out <- do.call(cbind, out)
out
# 1 2 3 4
# v11 1.2629543 1.329799 1.272429 0.4146414
# v12 -0.3262334 NA NA -1.5399500
# NA NA NA -0.9285670
答案 3 :(得分:0)
这是使用矩阵索引的完美案例,因为您已经拥有行索引。
以下是如何做到的:
matrix
基本上,您首先要创建一个填充了NA
值的df
,然后使用“v”(您的行索引)创建列索引,该矩阵的子集,以及将值替换为“df”中未列出的值。
{{1}}来自useR的答案。