我有一个如下所示的Excel工作表:
2015 2015 2016 2016 2017 2017 Name Height Weight Height Weight Height Weight Alice 12 34 56 78 90 12 Bob 55 55 55 55 55 55 ...
我的目标是产生一个整洁的数据框架,例如:
Name Year Height Weight Alice 2015 12 34 Alice 2016 56 78 Alice 2017 90 12 Bob 2015 55 55 Bob 2016 55 55 Bob 2017 55 55 ...
如果年份行不存在,我可以看到如何使用read_excel
中的gather
然后使用tidyverse
中的doc_id := "Can35qPeFkm9Xgmp9+aj3g=="
base64_decode, err := base64.StdEncoding.DecodeString(doc_id)
if err != nil {
log.Fatal("error:", err)
}
fmt.Println(hex.EncodeToString(base64_decode))
创建数据框,但是我不知道如何用两个标题行来做到这一点。我遇到的主要问题是,显然一列只能有一个名称,但似乎我想至少暂时为每个列使用两个名称。最好的方法是什么?
答案 0 :(得分:3)
这是一个相当普遍的问题(人们实际上使用的是这样的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
分隔Height和Weight变量。由于原始数据中的第二个标题行是文本,因此我们还将在该步骤中将这些值转换为数字。
答案 1 :(得分:2)
这很棘手,但是在从Excel文件中获取数据时很常见。我将您的数据粘贴到xlsx文件中,并使用readxl::read_excel
进行读取,但是出于可重复性的考虑,我也在此处粘贴了dput
的输出。我将col_names = F
设置为仅具有伪列名,从而在行中为我提供了这两个标题级别的每一个,如下所示:
library(dplyr)
library(tidyr)
# df <- readxl::read_excel("multicols.xlsx", col_names = F)
df <- structure(list(...1 = c(NA, "Name", "Alice", "Bob"), ...2 = c("2015",
"Height", "12", "55"), ...3 = c("2015", "Weight", "34", "55"),
...4 = c("2016", "Height", "56", "55"), ...5 = c("2016",
"Weight", "78", "55"), ...6 = c("2017", "Height", "90", "55"
), ...7 = c("2017", "Weight", "12", "55")), row.names = c(NA,
-4L), class = c("tbl_df", "tbl", "data.frame"))
df
#> # A tibble: 4 x 7
#> ...1 ...2 ...3 ...4 ...5 ...6 ...7
#> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 <NA> 2015 2015 2016 2016 2017 2017
#> 2 Name Height Weight Height Weight Height Weight
#> 3 Alice 12 34 56 78 90 12
#> 4 Bob 55 55 55 55 55 55
年份在第一行中,而度量在第二行中,所以我将其中的每个都拉出来了:
(yrs <- df[1,])
#> # A tibble: 1 x 7
#> ...1 ...2 ...3 ...4 ...5 ...6 ...7
#> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 <NA> 2015 2015 2016 2016 2017 2017
(cols <- df[2,])
#> # A tibble: 1 x 7
#> ...1 ...2 ...3 ...4 ...5 ...6 ...7
#> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 Name Height Weight Height Weight Height Weight
然后我将这两个粘贴在一起以获得一个体面的列名向量:
clean_names <- stringr::str_remove(paste(cols, yrs, sep = "_"), "_NA")
clean_names
#> [1] "Name" "Height_2015" "Weight_2015" "Height_2016" "Weight_2016"
#> [6] "Height_2017" "Weight_2017"
现在我可以删除这两行并设置适当的名称:
df %>%
slice(-1:-2) %>%
setNames(clean_names)
#> # A tibble: 2 x 7
#> Name Height_2015 Weight_2015 Height_2016 Weight_2016 Height_2017
#> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 Alice 12 34 56 78 90
#> 2 Bob 55 55 55 55 55
#> # … with 1 more variable: Weight_2017 <chr>
最后,将数据重塑为长形,将键分为小节(高度或重量)和年份,然后再扩展回宽形。
df %>%
slice(-1:-2) %>%
setNames(clean_names) %>%
gather(key, value, -Name) %>%
separate(key, into = c("measure", "year")) %>%
spread(key = measure, value)
#> # A tibble: 6 x 4
#> Name year Height Weight
#> <chr> <chr> <chr> <chr>
#> 1 Alice 2015 12 34
#> 2 Alice 2016 56 78
#> 3 Alice 2017 90 12
#> 4 Bob 2015 55 55
#> 5 Bob 2016 55 55
#> 6 Bob 2017 55 55
答案 2 :(得分:1)
您想要做的就是将数据从宽格式转变为长格式或将其重塑。
假设您的数据存储在W 34th St, New York, NY 10001, USA
中。这是一种dt
方法(语法比tidyverse好):
data.table
输出:
library(data.table)
dt2 <- data.table(melt(dt, id.vars = "Name", variable.name = "Measurement", value.name = "Value"), year = rep(rep(2015:2017, each = 2), times = 2))
您会注意到,我在同一列中有> dt2
Name Measurement Value year
1: Alice Height 12 2015
2: Bob Height 55 2015
3: Alice Weight 34 2016
4: Bob Weight 55 2016
5: Alice Height 56 2017
6: Bob Height 55 2017
7: Alice Weight 78 2015
8: Bob Weight 55 2015
9: Alice Height 90 2016
10: Bob Height 55 2016
11: Alice Weight 12 2017
12: Bob Weight 55 2017
和Weight
个测量值。我建议您这样做,而不是为每个变量单独添加一列,因为它与Height
语法兼容。
对数据感到好奇的是,您有两行作为标题。这意味着您将不得不根据数据调整我答案中的group by
参数。
通常,要创建您的year = ...
列,您需要:
year