2016-10-03 138 views
-1

我需要一些帮助来重新设计R包中函数的输出。在R中重塑一个数据帧

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

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输出看起来是这样的:

enter image description here

但是,我想重新设计这个数据帧看起来像output_imfr的输出:

enter image description here

可悲的是,我没有那么高级的用户,但没有找到的东西,可以帮助我。在将output_IMFData的形状转换成第二个“面板数据相关”数据框架的形状中,我的基本问题是我不知道如何处理output_IMFData中的Obs,这种方式不会失去与“对应”参考代码@REF-AREAoutput_IMFData也就是说,在列@REF-AREA中有国名代码,Obs中的列有它们各自的时间序列数据,这是使用面板数据非常麻烦的方式,因此我想将该数据帧重塑为output_imfr数据帧的更好形式

回答

2

感兴趣的数据存储在列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> 
+0

对不起 - 我误解了您最初的代码,并认为它是从本地数据库中调用和/或需要大下载(我以前从未使用过'imfr'包)。看到编辑后的一些代码应该可以为你实际工作(请注意,'gather'将**不适用于这些数据) –

+0

太棒了。如果有时间的话它会节省很多这就是我想知道的。 – msh855

+0

Pererson,假设一个有点扭曲,而不是下载一个系列想下载两个。这种扭曲的MWE将是在'queryfilter'列表中将'CL_INDICATOR_IFS'重新定义为CL_INDICATOR_IFS = c(“IAD_BP6_USD”,“NGDP_EUR”)。换句话说,信件不仅应以@ REF-AREA为基础,而且还应以“@ INDICATOR”为指标。你能否建议你的代码应该如何修改? – msh855

2

这里的另一种方法:

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 
    } 
} 
+1

这是非常直观和智能的答案,但一旦数据帧变大,它可能变得非常缓慢。 – msh855