2015-08-03 37 views
11

我有面板結構的數據幀:2周的觀察對每個單元由兩年:如何在tidyr傳播後控制新變量的名字?

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更換新的變量名稱?

回答

11

可以使用backticks列名以數字和filter應該按預期工作

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

或者另一種選擇是使用unite創建第二列「YEAR1」後加入兩列單columnn字符串'y'。

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 

即使我們可以通過paste

mydf %>% 
    mutate(year=paste('y', year, sep="_")) %>% 
    spread(year, value) %>% 
    filter(y_2012 > 0.5) 
2

另一個選項中mutate改變「年」列是使用setNames()功能作爲管道,接下來的事情:

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

使用setNames的唯一問題是,當你spread()他們時,你必須確切知道你的列將會是什麼。大多數情況下,這不是問題,特別是如果您正在半互動地工作。

但是,如果您在原始數據中缺少鍵/值對,有可能不會顯示爲列,並且最終可能會在您不知道它的情況下錯誤地命名您的列。誠然,setNames()將拋出一個錯誤,如果名稱的數量不匹配的列數,那麼你已經有了一個位錯誤的檢驗內置的。

儘管如此,使用setNames()的便利性已經壓倒了更多的風險往往不適合我。

相關問題