2017-06-16 64 views
0

我使用一個返回數據幀列表的API(Rblpapi bdh()函數)。我希望使用列表的names()作爲組合單個數據框中的新列來將數據放在整齊的格式中。我有一個解決方案,但它很容易出錯,比我需要的慢,我懷​​疑。是否有更清晰的方式來整理數據框的列表?

#create example data set 
library(tidyr) 

obsA <- data_frame(
    date = as.Date('2009-01-01') + 0:2, 
    X = rnorm(3, 0, 1), 
    Y = rnorm(3, 0, 2), 
    Z = rnorm(3, 0, 4) 
) 
obsB <- data_frame(
    date = as.Date('2009-01-01') + 0:2, 
    X = rnorm(3, 10, 1), 
    Y = rnorm(3, 10, 2), 
    Z = rnorm(3, 10, 4) 
) 

obs<-list(obsA=obsA,obsB=obsB) 

我可以很容易地創建一個單一的數據框,但它將單個列表名稱放入唯一的行名稱中。

#create single data frame 
obs_long<-do.call("rbind",obs) 

#don't like this 
rownames(obs_long) 
#[1] "obsA.1" "obsA.2" "obsA.3" "obsB.1" "obsB.2" "obsB.3" 
names(obs_long) 
#[1] "date" "X" "Y" "Z" 

我可以拉出的行,使用一個正則表達式剝離添加的行標識符和mutate()一個新列。

#Full solution but ungainly. 
# Extra step to convert row names to a column. Risk of parsing error if 
# a period is in item name. 
tidy_obs<-do.call("rbind",obs) #%>% 
    mutate(item=str_extract(rownames(.),"[A-Za-z0-9 ]+"))%>% 
    select(date,item,everything())%>% 
    group_by(item)%>%arrange(date) 

# > tidy_obs 
# # A tibble: 6 x 5 
# # Groups: item [2] 
# date   item   X   Y   Z 
# <date>  <chr>  <dbl>  <dbl>  <dbl> 
# 1 2009-01-01 obsA -0.1030362 2.274885 -4.134265 
# 2 2009-01-01 obsB 8.4210832 7.604203 13.449731 
# 3 2009-01-02 obsA -0.2279141 -2.748717 4.372599 
# 4 2009-01-02 obsB 12.8940563 10.594164 8.108275 
# 5 2009-01-03 obsA 0.5749725 -4.041280 -0.524420 
# 6 2009-01-03 obsB 10.1158769 12.684331 8.248651 

這工作,但我想知道是否有避免的mutate()額外的步驟和/或str_extract()的分析異常的風險更直接的方式。謝謝!

+0

如何改變你的'列表'稍微'cbind' datafram (obsA = cbind(obsA,item =「obsA」),obsB = cbind(obsB,item =「obsB」))'? W –

回答

2

可以使用dplyr::bind_rows.id參數:

.ID數據幀標識符。

當提供.id時,會創建一個新的 標識符列以將每一行鏈接到其原始數據框。 標籤是從指定的參數中取到bind_rows()。 當提供了一個 數據框列表時,標籤取自列表的名稱 。如果找不到名稱,則使用數字序列。

bind_rows(obs, .id = "item") 

# A tibble: 6 x 5 
# item  date   X   Y   Z 
# <chr>  <date>  <dbl>  <dbl>  <dbl> 
#1 obsA 2009-01-01 -1.73508885 -0.4402811 7.342978 
#2 obsA 2009-01-02 1.17149983 -0.5429690 8.167079 
#3 obsA 2009-01-03 0.08631895 -0.1430551 5.925108 
#4 obsB 2009-01-01 9.66203430 7.1094147 15.577023 
#5 obsB 2009-01-02 10.43062660 9.6160614 15.077929 
#6 obsB 2009-01-03 8.80792988 8.9604396 7.413831 
+0

就是這樣!我知道我錯過了一些簡單的事情。謝謝! – Art

1

也有可能與data.tablerbindlist

library(data.table) 
rbindlist(obs, idcol = "item") 
# item  date   X   Y   Z 
#1: obsA 2009-01-01 -0.2900620 2.694434 2.555925 
#2: obsA 2009-01-02 -1.0221531 -4.172495 -4.357794 
#3: obsA 2009-01-03 0.2389569 -1.088882 -4.944420 
#4: obsB 2009-01-01 9.4713142 10.433553 9.319284 
#5: obsB 2009-01-02 10.0967994 11.941084 13.589136 
#6: obsB 2009-01-03 9.9403227 11.727769 17.792899 

一個基礎R方法也可能是使用MapReduce

Reduce(rbind, Map(function(x,name) cbind(x,item = name), obs, names(obs))) 
相關問題