如何将"reshape"这些数据转化为可用的格式?

How to "reshape" this data into a useable format?

我有这个数据集,它的格式很奇怪。

看起来像这样:

          1971 1971 1971 1972 1972 1972
          var1 var2 var3 var1 var2 var3
person1     37    2    1   65    5    3   
person2     65    2    1  123    3    1   
person3     23    3    1   13    6    2   

我想知道是否有任何简单的方法可以将这些数据转换成如下所示:

         year  var1 var2 var3
person1  1971    37    2    1   
person1  1972    65    5    3   
person2  1971    65    2    1 
person2  1972   123    3    1
person3  1971    23    3    1
person3  1972    13    6    2

我想我要做的是反向重塑数据或其他东西。我已经研究了 melt、cast 和 transpose,但我无法得到任何可用的结果。

这是我试图找出您需要的东西。如果某些地方不精确,请根据您的意愿进行修改。我使用了 3 个库,但别担心。在 R 中,这些经常被放在一起,并且无论如何都是为了将​​来知道。我本可以用基本的 R 编写代码,但这意味着更长的代码

input.csv

,1971,1971,1971,1972,1972,1972
,var1,var2,var3,var1,var2,var3
person1,37,2,1,65,5,3
person2,65,2,1,123,3,1
person3,23,3,1,13,6,2

修改表示的代码

library(reshape2)
library(tidyr)
library(dplyr)

input = read.table("input.csv", sep=",", na.strings="", header=T)[-1,]
converted_input = input %>%
  tidyr::gather(year, value, -X) %>%
  dplyr::mutate(
    var=paste0("var", as.numeric(gsub("^X.*", "0", gsub(".*\.([0-9])$", "\1", year)))+1),
    year=gsub("X([^.]+).*", "\1", year)) %>%
  reshape2::dcast(X + year ~ var, value.var="value") %>%
  dplyr::rename(person=X)

print(converted_input)

最终结果

 person year var1 var2 var3
person1 1971   37    2    1
person1 1972   65    5    3
person2 1971   65    2    1
person2 1972  123    3    1
person3 1971   23    3    1
person3 1972   13    6    2

这是一种难以处理的格式,因为原始文件中的 header 列信息来自两行。我的做法是读取除第一行以外的所有数据,然后再读取第一行进行数据操作。

第一步:读取第一行以外的数据

dat <- read.table(text = "         1971 1971 1971 1972 1972 1972
          var1 var2 var3 var1 var2 var3
                  person1     37    2    1   65    5    3   
                  person2     65    2    1  123    3    1   
                  person3     23    3    1   13    6    2",
                  header = TRUE, stringsAsFactors = FALSE, skip = 1)
dat
#         var1 var2 var3 var1.1 var2.1 var3.1
# person1   37    2    1     65      5      3
# person2   65    2    1    123      3      1
# person3   23    3    1     13      6      2

第 2 步:读取第一行作为向量

Year <- read.table(text = "         1971 1971 1971 1972 1972 1972
          var1 var2 var3 var1 var2 var3
                   person1     37    2    1   65    5    3   
                   person2     65    2    1  123    3    1   
                   person3     23    3    1   13    6    2",
                   header = FALSE, stringsAsFactors = FALSE, nrows = 1)

# Convert Year to a vector
Year <- unlist(Year)
Year
#   V1   V2   V3   V4   V5   V6 
# 1971 1971 1971 1972 1972 1972

第 3 步:合并 header 信息

library(tidyverse)

# Rename the dat dat data frame
dat2 <- dat %>%
  setNames(paste(names(.), Year, sep = "_")) %>%
  setNames(sub("\.\d+", "", names(.)))
dat2
#         var1_1971 var2_1971 var3_1971 var1_1972 var2_1972 var3_1972
# person1        37         2         1        65         5         3
# person2        65         2         1       123         3         1
# person3        23         3         1        13         6         2

现在 dat2 是我们可以使用的格式。

第 4 步:重塑数据框

# Reshape the dtaa frame
dat3 <- dat2 %>%
  rownames_to_column(var = "Person") %>%
  gather(Variable, Value, -Person) %>%
  separate(Variable, into = c("Var", "Year")) %>%
  spread(Var, Value)
dat3
#    Person Year var1 var2 var3
# 1 person1 1971   37    2    1
# 2 person1 1972   65    5    3
# 3 person2 1971   65    2    1
# 4 person2 1972  123    3    1
# 5 person3 1971   23    3    1
# 6 person3 1972   13    6    2

dat3是最终输出。