2016-10-03 12 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 в форму второй «картографической» модели данных, которая заключается в том, что я не знаю, как обрабатывать Obs в output_IMFData способом, который не может потерять «соответствие» с помощью Код ссылки @REF-AREA в output_IMFData. То есть в колонке @REF-AREA имеются коды названий стран, а в столбце Obs приведены соответствующие данные временных рядов. Это очень громоздкий способ работы с данными панели, и поэтому я хочу изменить этот кадр данных на гораздо лучше, форма output_imfr dataframe.

ответ

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

Персон, предположим, что он делает небольшой поворот, и вместо того, чтобы загружать одну серию, нужно скачать два. MWE для этого поворота будет состоять в том, чтобы переопределить 'CL_INDICATOR_IFS 'как' CL_INDICATOR_IFS = c ("IAD_BP6_USD", "NGDP_EUR") 'в' queryfilter'. Другими словами, соответствие должно основываться не только на @ 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