在 R 中重塑数据框

Reshaping a dataframe in R

我需要一些帮助来重新设计来自 R 包的函数的输出。

我的范围是以看起来与 output_imfr 的形状非常相似的方式重塑一个名为 output_IMFData 的数据框。 重现这些数据帧的 MWE 代码是

library(imfr)

output_imfr <- imf_data(database_id="IFS", indicator="IAD_BP6_USD", country = "", start = 2010, end = 2014, freq = "A", return_raw =FALSE, print_url = T, times = 3)

output_IMFData

library(IMFData)
databaseID  <- "IFS"
startdate   <- "2010"
enddate     <- "2014"
checkquery  <- FALSE
queryfilter  <- list(CL_FREA = "A", CL_AREA_IFS = "", CL_INDICATOR_IFS = "IAD_BP6_USD")
output_IMFData <- CompactDataMethod(databaseID, queryfilter, startdate, enddate, 
                                   checkquery)

output_IMFData 的输出如下所示:

但是,我想重新设计这个数据框,使其看起来像 output_imfr:

的输出

遗憾的是,我不是那么高级的用户,找不到可以帮助我的东西。我将 output_IMFData 的形状转换为第二个“panel-data-looking”数据框架的形状的基本问题是我不知道如何处理 output_IMFData 中的 Obsoutput_IMFData中引用代码@REF-AREA的"correspondence"不能丢失,即@REF-AREA列中有国家名称代码和[=中的列18=] 有各自的时间序列数据。这是处理面板数据的非常麻烦的方式,因此我想将该数据框重塑为 output_imfr 数据框的更好形式。

感兴趣的数据存储在列 Obs 的列表中。这是拆分数据的 dplyr 解决方案,打开列表,然后将它们拼接在一起。

longData <-
  output_IMFData %>%
  split(1:nrow(.)) %>%
  lapply(function(x){
    data.frame(
      iso2c = x[["@REF_AREA"]]
      , x$Obs
    )
  }) %>%
  bind_rows()

head(longData)

给出:

  iso2c X.TIME_PERIOD      X.OBS_VALUE X.OBS_STATUS
1    FJ          2010 47.2107721901621         <NA>
2    FJ          2011         48.28347         <NA>
3    FJ          2012 51.0823499999999         <NA>
4    FJ          2013 157.015648875072         <NA>
5    FJ          2014 186.623232882226         <NA>
6    AW          2010 616.664804469274         <NA>

这是另一种方法:

NewDataFrame <- data.frame(iso2c=character(), 
                 year=numeric(),
                 IAD_BP6_USD=character(), 
                 stringsAsFactors=FALSE)

newrow = 1

for(i in 1:nrow(output_IMFData)) { # for each row of your cludgy df
   for(j in 1:length(output_IMFData$Obs[[i]]$`@TIME_PERIOD`)) {  # for each year
     NewDataFrame[newrow,'iso2c']<-output_IMFData[i, '@REF_AREA']
     NewDataFrame[newrow,'year']<-output_IMFData$Obs[[i]]$`@TIME_PERIOD`[j]
     NewDataFrame[newrow,'IAD_BP6_USD']<-output_IMFData$Obs[[i]]$`@OBS_VALUE`[j]
     newrow<-newrow + 1 # increment down a row
   }
}