R 使用指示向量将宽形状改为长形状

R 使用指示向量将宽形状改为长形状,r,dplyr,reshape,tidyr,R,Dplyr,Reshape,Tidyr,我有这样一个数据框: 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 v21 v31 v41 v12 NA NA v42 NA NA NA v43 某些列是对同一主题的重复观察,例如v11和v12是来自同一主题的两个观察。 v21和v32仅为单一观察结果v4x有三个观察结果 我

我有这样一个数据框:

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  v21 v31  v41
v12   NA  NA  v42
 NA   NA  NA  v43
某些列是对同一主题的重复观察,例如
v11
v12
是来自同一主题的两个观察。
v21
v32
仅为单一观察结果<代码>v4x有三个观察结果

我想重塑数据帧,使其如下所示:

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  v21 v31  v41
v12   NA  NA  v42
 NA   NA  NA  v43
注意,它应该包含变量的值,而不是它们的名称

我有一个指示向量,用于标记观察结果:

v <- c(1, 2, 1, 1, 1, 2, 3)

v这里有一个使用
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")

下面是一个使用
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")

您还可以使用
reformae2
transform
中的
melt
dcast
执行此操作:

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您也可以使用
melt
dcast
restrape2
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这是base
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)
set.seed(0)

df这是base
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)
set.seed(0)

df这是使用矩阵索引的完美案例,因为您已经有了行索引

以下是如何做到这一点:

M <- matrix(NA, nrow = max(v), ncol = sum(v == 1))
M[cbind(v, cumsum(v == 1))] <- unlist(df, use.names = FALSE)
M
#            [,1]     [,2]       [,3]      [,4]
# [1,] -0.5604756 1.558708 0.07050839 0.1292877
# [2,] -0.2301775       NA         NA 1.7150650
# [3,]         NA       NA         NA 0.4609162

M这是使用矩阵索引的完美案例,因为您已经有了行索引

以下是如何做到这一点:

M <- matrix(NA, nrow = max(v), ncol = sum(v == 1))
M[cbind(v, cumsum(v == 1))] <- unlist(df, use.names = FALSE)
M
#            [,1]     [,2]       [,3]      [,4]
# [1,] -0.5604756 1.558708 0.07050839 0.1292877
# [2,] -0.2301775       NA         NA 1.7150650
# [3,]         NA       NA         NA 0.4609162

M谢谢,但这是可以概括的吗?在我的真实数据集中,变量名是完全不同的,并且没有表示它们是哪些观测值的结尾。它只是在向量
v
@spore234中,没有变量名,否则你怎么知道元素应该是哪一列/哪一行呢?我认为你的问题的前提是你有那些一致的变量名。例如,假设您的变量名现在从
a
g
,您怎么知道
a
b
在第1列?您是对的,我在示例中犯了一个错误。第一行总是完整的。因此,每个新的“1”表示新列的开始。是的,正确。它应该是这样的:“如果1出现开始新列,如果不是1填充行x”。@userR啊,是的,我现在明白了。不错的解决方案+1。我还在想着OP想要的东西…谢谢,但这是可以概括的吗?在我的真实数据集中,变量名是完全不同的,并且没有表示它们是哪些观测值的结尾。它只是在向量
v
@spore234中,没有变量名,否则你怎么知道元素应该是哪一列/哪一行呢?我认为你的问题的前提是你有那些一致的变量名。例如,假设您的变量名现在从
a
g
,您怎么知道
a
b
在第1列?您是对的,我在示例中犯了一个错误。第一行总是完整的。因此,每个新的“1”表示新列的开始。是的,正确。它应该是这样的:“如果1出现开始新列,如果不是1填充行x”。@userR啊,是的,我现在明白了。不错的解决方案+1。我仍然在思考OP想要什么…这与我的原始答案类似,但OP提到重塑不应基于原始列名,而应仅基于提供的指示向量
v
。这与我的原始答案类似,但OP提到,重塑不应基于原始列名,而应仅基于提供的指示符向量
v
。这个问题没有什么不清楚的地方。这个问题没有什么不清楚的地方。这是可行的,比“tidyr”方法更快,但似乎有些过分了!这是可行的,并且比“tidyr”方法更快,但似乎有点过头了!