问题 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


10629
2017-08-03 13:09


起源



答案:


您可以使用 backticks 对于以数字和开头的列名称 filter 应该按预期工作

  mydf %>%
      spread(year, value) %>%
      filter(`2012` > 0.5)
  #  id      2012      2013
  #1  3 0.8453762 0.3346603

或者另一种选择是使用 unite 在使用字符串'y'创建第二列'year1'后,将两列连接到一个列。

  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)

12
2017-08-03 13:11





另一种选择是使用 setNames() 作为管道中的下一个功能:

mydf %>%
    spread(mydf, year, value) %>%
    setNames( c("id", "y2012", "y2013") ) %>%
    filter(y2012 > 0.5)

使用setNames的唯一问题是你必须准确知道你的列将是什么 spread() 他们。大多数时候,这不是问题,特别是如果你是半交互式工作的话。

但是,如果您在原始数据中缺少键/值对,则有可能它不会显示为列,并且您最终可能会错误地命名列,甚至不知道它。当然, setNames() 如果名称的数量与列数不匹配,则会抛出错误,因此您内置了一些错误检查。

仍然,使用方便 setNames() 对我来说,风险往往超过风险。


2
2018-03-08 14:06