是否有更简洁的方法来整理数据框列表?

时间:2017-06-16 18:15:06

标签: r dplyr tidyr

我使用返回数据框列表的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()的解析异常风险。谢谢!

2 个答案:

答案 0 :(得分:2)

您可以将ApplicationListenerdplyr::bind_rows参数一起使用:

  

.id数据帧标识符。

     

提供.id时,新列   创建标识符以将每一行链接到其原始数据帧。   标签取自bind_rows()的命名参数。 当a   提供数据帧列表,标签取自名称   列表。如果没有找到名称,则使用数字序列。

.id

答案 1 :(得分:1)

也可以使用data.table&#39; rbindlist

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