如何控制新变量' tidyr传播之后的名字?

时间:2015-08-03 13:09:21

标签: r dplyr tidyr

我有一个带有面板结构的数据框:两年内每个单元的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中的新变量名吗?

5 个答案:

答案 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)

dplyr中的

rename()应该可以解决问题

library(tidyr); library(dplyr)
mydf %>%
  spread(year,value)%>%
  rename(y2012 = '2012',y2013 = '2013')%>%
  filter(y2012>0.5)