首页 > 解决方案 > 用两行作为标题重塑多变量数据(从宽到长)

问题描述

我有一个格式如下的 Excel 工作表:

             2015 2015 2016 2016 2017 2017
名称 身高 体重 身高 体重 身高 体重  
爱丽丝 12 34 56 78 90 12      
鲍勃 55 55 55 55 55 55     
...

我的目标是生成一个整洁的数据框,例如:

姓名 年龄 身高 体重
爱丽丝 2015 12 34
爱丽丝 2016 56 78
爱丽丝 2017 90 12
鲍勃 2015 55 55
鲍勃 2016 55 55
鲍勃 2017 55 55
...

如果年行不存在,我可以看到如何使用read_excel然后gather从创建数据框,但我不明白如何使用两个标题行来执行此操作。tidyverse我被卡住的主要一点是,显然一列只能有一个名称,但似乎我想至少暂时为每列有两个名称。这样做的最佳方法是什么?

标签: rtidyr

解决方案


这是一个相当普遍的问题(人们实际上使用这样的 excel 工作簿),但涉及在 R 中解决的几个步骤。这是一种方法,我假设您的数据框被调用dat

library(dplyr)
library(tidyr)
library(magrittr) # for the two-way pipe %<>%

# Start by renaming your columns to include both the year and variable
# The use of '-' to separate the parts is for convenience in the regex below
names(dat)[2:ncol(dat)] <- paste(dat[1, 2:ncol(dat)],
                                 names(dat)[2:ncol(dat)],
                                 sep = "-")
names(dat)[1] <- "Name"
names(dat) <- sub("__\\d+", "", names(dat))

# Drop the now useless first row
dat <- dat[2:nrow(dat), ]

# Transform the data
dat %<>%
  gather(key = var, value = val, -Name) %>%
  mutate(Year = sub("^.*?-", "", var),
         var = sub("-\\d+$", "", var)) %>%
  spread(key = var, value = as.numeric(val))

转换数据的管道序列的工作方式如下:首先,您的直觉是正确的,我们需要使用gather它来从宽转换为长。其次,我们创建“Year”变量并从临时“var”变量中删除这些数字。最后,我们必须使用spread单独的高度和重量变量。由于原始数据中的第二个标题行是文本,我们还将在该步骤中将这些值转换为数字。


推荐阅读