我有一个带有面板结构的数据框:两年内每个单元的2个观察结果:
library(tidyr)
mydf <- data.frame(
id = rep(1:3, rep(2,3)),
year = rep(c(2012, 2013), 3),
value = runif(6)
)
mydf
# id year value
#1 1 2012 0.09668064
#2 1 2013 0.62739399
#3 2 2012 0.45618433
#4 2 2013 0.60347152
#5 3 2012 0.84537624
#6 3 2013 0.33466030
我想将此数据重新整理为宽格式,可以使用tidyr::spread
轻松完成。但是,由于year
变量的值是数字,我的新变量的名称也会变成数字,这使得它的使用更加困难。
spread(mydf, year, value)
# id 2012 2013
#1 1 0.09668064 0.6273940
#2 2 0.45618433 0.6034715
#3 3 0.84537624 0.3346603
我知道我可以轻松地重命名列。但是,如果我想在其他操作的链中重塑,则会变得不方便。例如。以下几行显然没有意义。
library(dplyr)
mydf %>% spread(year, value) %>% filter(2012 > 0.5)
以下作品但不简洁:
tmp <- spread(mydf, year, value)
names(tmp) <- c("id", "y2012", "y2013")
filter(tmp, y2012 > 0.5)
知道如何更改spread
中的新变量名吗?
答案 0 :(得分:14)
您可以将backticks
用于以数字开头的列名称,filter
应按预期工作
mydf %>%
spread(year, value) %>%
filter(`2012` > 0.5)
# id 2012 2013
#1 3 0.8453762 0.3346603
或者另一个选项是在使用字符串'y'创建第二列'year1'后,使用unite
将两列连接到一个列。
mydf %>%
mutate(year1='y') %>%
unite(yearN, year1, year) %>%
spread(yearN, value) %>%
filter(y_2012 > 0.5)
# id y_2012 y_2013
#1 3 0.8453762 0.3346603
即使我们可以使用mutate
paste
中的“年份”列
mydf %>%
mutate(year=paste('y', year, sep="_")) %>%
spread(year, value) %>%
filter(y_2012 > 0.5)
答案 1 :(得分:6)
我知道自从最初提出这个问题以来已经过去了几年,但是为了后代,我还要强调sep
的{{1}}参数。如果不是spread
,它将用作键名和值之间的分隔符:
NULL
这与问题中所要求的不完全相同,但足以满足我的目的。参见mydf %>%
spread(key = year, value = value, sep = "")
# id year2012 year2013
#1 1 0.15608322 0.6886531
#2 2 0.04598124 0.0792947
#3 3 0.16835445 0.1744542
。
答案 2 :(得分:5)
另一个选择是使用setNames()
函数作为管道中的下一个东西:
mydf %>%
spread(mydf, year, value) %>%
setNames( c("id", "y2012", "y2013") ) %>%
filter(y2012 > 0.5)
使用setNames的唯一问题是,当您spread()
时,您必须确切知道列的内容。大多数时候,这不是问题,特别是如果你是半交互式的。
但是,如果您在原始数据中缺少键/值对,则有可能它不会显示为列,并且您最终可能会错误地命名列,甚至不知道它。当然,如果名称的数量与列数不匹配,setNames()
将抛出错误,因此您内置了一些错误检查。
尽管如此,使用setNames()
的便利性对我来说往往超过风险。
答案 3 :(得分:2)
使用spread()
的后继者pivot_wider()
,我们可以为创建的列添加前缀:
library(tidyr)
set.seed(1)
mydf <- data.frame(
id = rep(1:3, rep(2,3)),
year = rep(c(2012, 2013), 3),
value = runif(6)
)
pivot_wider(mydf, names_from = "year", values_from = "value", names_prefix = "y")
#> # A tibble: 3 x 3
#> id y2012 y2013
#> <int> <dbl> <dbl>
#> 1 1 0.266 0.372
#> 2 2 0.573 0.908
#> 3 3 0.202 0.898
由reprex package(v0.3.0)于2019-09-14创建
答案 4 :(得分:0)
rename()应该可以解决问题
library(tidyr); library(dplyr)
mydf %>%
spread(year,value)%>%
rename(y2012 = '2012',y2013 = '2013')%>%
filter(y2012>0.5)