2017-04-20 25 views
0

我有以下列表:中提取多個列,並保存在data.frame

library(rjson) 
j <- fromJSON(file='https://esgf-data.dkrz.de/esg-search/search/?offset=0&limit=1000&type=Dataset&replica=false&latest=true&project=CORDEX&domain=EUR-11&experiment=rcp85&time_frequency=day&facets=rcm_name%2Cproject%2Cproduct%2Cdomain%2Cinstitute%2Cdriving_model%2Cexperiment%2Cexperiment_family%2Censemble%2Crcm_version%2Ctime_frequency%2Cvariable%2Cvariable_long_name%2Ccf_standard_name%2Cdata_node&format=application%2Fsolr%2Bjson') 

我很感興趣,從這個成分提取數據:j$response$docs,這是一個列表的列表。 '內部'列表都應該有相同的名稱。

我想將輸出保存到data.frame()tibble()

這下面的作品,並給出了所需的輸出,對幾個選定的變量:

nmod <- length(j$response$docs) 
for (i in 1:nmod) { 
    #select one list at a time 
    j1 <- j$response$docs[[i]] 
    tmp <- data.frame(variable=j1$variable, 
         variable_long_name=j1$variable_long_name, 
         rcm_name=j1$rcm_name, 
         driving_model=j1$driving_model, 
         cf_standard_name=j1$cf_standard_name 
         ) 
    #join them 
    if (i==1) { 
     d <- tmp 
    } else { 
     d <- rbind(d, tmp) 
    } 
} 

不過,我想知道是否有一個更優雅的和有效的方式,也許用tidyrdplyrpurrr,這也允許我選擇所有的「列」,而不僅僅是那裏選擇的幾個。

+0

將列表綁定在一起可以通過使用來自'dplyr'的'bind_rows'進行整理,該列表需要列表。它可以移到循環之外,你不需要if語句。 – Lespied

+0

你也許可以用'lapply(,'[[')''來提取第一個列表 – Lespied

+0

@Lespied然而,我認爲這不適用於多個內部列表,對吧?我的意思是,我可以用lapply(j $ response $ docs,'[[','variable_long_name')'一次提取一個,但一次只能提取一個。我錯過了一個簡單的方法來做到這一點? – AF7

回答

2

您可以幫助從包purrr做到這一點。我認爲at_depth可能在這裏工作,但我最終使用嵌套map_df

library(purrr) 

你的變量的長度不同,所以首先要做的是確保每個變量的長度是1。這可以通過摺疊內部列表中的每個元素與paste來完成。我用逗號分隔符。通過map_df執行此操作將返回1行tibble

下面是第一個內部列表的示例。

map_df(j$response$docs[[1]], paste, collapse = ",") 

現在我們可以通過外循環列表,使得1列tibble每個。我們使用map_df將它們中的每一個綁定在一起。輸出爲832行tibble,每個列表一行。我使用.id參數來爲結果添加分組變量,這可能不是必需的。

d1 = map_df(j$response$docs, ~map_df(.x, paste, collapse = ",")) 
d1 

# A tibble: 832 × 45 
    group                         id version 
    <chr>                        <chr> <chr> 
1  1 cordex.output.EUR-11.DMI.ICHEC-EC-EARTH.rcp85.r3i1p1.HIRHAM5.v1.day.clh.v20131119|cordexesg.dmi.dk 20131119 
2  2 cordex.output.EUR-11.DMI.ICHEC-EC-EARTH.rcp85.r3i1p1.HIRHAM5.v1.day.clivi.v20131119|cordexesg.dmi.dk 20131119 
3  3 cordex.output.EUR-11.DMI.ICHEC-EC-EARTH.rcp85.r3i1p1.HIRHAM5.v1.day.rsds.v20131119|cordexesg.dmi.dk 20131119 
4  4 cordex.output.EUR-11.DMI.ICHEC-EC-EARTH.rcp85.r3i1p1.HIRHAM5.v1.day.rlds.v20131119|cordexesg.dmi.dk 20131119 
5  5 cordex.output.EUR-11.DMI.ICHEC-EC-EARTH.rcp85.r3i1p1.HIRHAM5.v1.day.rsus.v20131119|cordexesg.dmi.dk 20131119 
6  6 cordex.output.EUR-11.DMI.ICHEC-EC-EARTH.rcp85.r3i1p1.HIRHAM5.v1.day.rlus.v20131119|cordexesg.dmi.dk 20131119 
7  7 cordex.output.EUR-11.DMI.ICHEC-EC-EARTH.rcp85.r3i1p1.HIRHAM5.v1.day.rsdt.v20131119|cordexesg.dmi.dk 20131119 
8  8 cordex.output.EUR-11.DMI.ICHEC-EC-EARTH.rcp85.r3i1p1.HIRHAM5.v1.day.rsut.v20131119|cordexesg.dmi.dk 20131119 
9  9 cordex.output.EUR-11.DMI.ICHEC-EC-EARTH.rcp85.r3i1p1.HIRHAM5.v1.day.rlut.v20131119|cordexesg.dmi.dk 20131119 
10 10 cordex.output.EUR-11.DMI.ICHEC-EC-EARTH.rcp85.r3i1p1.HIRHAM5.v1.day.psl.v20131119|cordexesg.dmi.dk 20131119 
# ... with 822 more rows, and 42 more variables: 

如果你想獲得了比長度1時的變量,如accessexperiment_family多行,可以使用tidyr::separate_rows將數據劃分到多個行。

tidyr::separate_rows(d1, experiment_family) 
+0

這是*正是*我正在尋找。一旦你掌握了它們的訣竅,'purrr'和'dplyr'就非常棒。 – AF7

0

代替rjson去與此:

library(jsonlite) 
j <- jsonlite::fromJSON('https://esgf-data.dkrz.de/esg-search/search/?offset=0&limit=1000&type=Dataset&replica=false&latest=true&project=CORDEX&domain=EUR-11&experiment=rcp85&time_frequency=day&facets=rcm_name%2Cproject%2Cproduct%2Cdomain%2Cinstitute%2Cdriving_model%2Cexperiment%2Cexperiment_family%2Censemble%2Crcm_version%2Ctime_frequency%2Cvariable%2Cvariable_long_name%2Ccf_standard_name%2Cdata_node&format=application%2Fsolr%2Bjson') 

# The names you wan to find in the nested returned data 
look_for <- c('variable','variable_long_name' , 
       'rcm_name','driving_model', 
       'cf_standard_name') 


new_df <- as.data.frame(sapply(look_for, function(i){ 
    unlist(j$response$docs[[i]]) 
})) 

str(new_df) 
'data.frame': 832 obs. of 5 variables: 
$ variable   : chr "clh" "clivi" "rsds" "rlds" ... 
$ variable_long_name: chr "High Level Cloud Fraction" "Ice Water Path" "Surface Downwelling Shortwave Radiation" "Surface Downwelling Longwave Radiation" ... 
$ rcm_name   : chr "HIRHAM5" "HIRHAM5" "HIRHAM5" "HIRHAM5" ... 
$ driving_model  : chr "ICHEC-EC-EARTH" "ICHEC-EC-EARTH" "ICHEC-EC-EARTH" "ICHEC-EC-EARTH" ... 
$ cf_standard_name : chr "cloud_area_fraction_in_atmosphere_layer" "atmosphere_cloud_ice_content" "surface_downwelling_shortwave_flux_in_air" "surface_downwelling_longwave_flux_in_air" ... 
相關問題