如何使用R在DataFrame列中解析JSON

时间:2017-02-01 20:18:02

标签: json r

我如何从这里来......

| ID | JSON Request                                                          |
==============================================================================
|  1 | {"user":"xyz1","weightmap": {"P1":0,"P2":100}, "domains":["a1","b1"]} |
------------------------------------------------------------------------------
|  2 | {"user":"xyz2","weightmap": {"P1":100,"P2":0}, "domains":["a2","b2"]} |
------------------------------------------------------------------------------

到这里(要求是在第2列中创建一个JSON表):

| User | P1 | P2 | domains | 
============================
| xyz1 |  0 |100 | a1, b1  |
----------------------------
| xyz2 |100 | 0  | a2, b2  |
----------------------------

以下是生成data.frame的代码:

raw_df <- 
  data.frame(
    id   = 1:2,
    json = 
      c(
        '{"user": "xyz2", "weightmap": {"P1":100,"P2":0}, "domains": ["a2","b2"]}', 
        '{"user": "xyz1", "weightmap": {"P1":0,"P2":100}, "domains": ["a1","b1"]}'
      ), 
    stringsAsFactors = FALSE
  )

5 个答案:

答案 0 :(得分:11)

如果您愿意以长格式工作(在这种情况下为domains),这里是一个整齐的解决方案(也使用jsonlite):

library(jsonlite)
library(dplyr)
library(purrr)
library(tidyr)

d <- data.frame(
  id = c(1, 2),
  json = c(
    '{"user":"xyz1","weightmap": {"P1":0,"P2":100}, "domains":["a1","b1"]}',
    '{"user":"xyz2","weightmap": {"P1":100,"P2":0}, "domains":["a2","b2"]}'
  ),
  stringsAsFactors = FALSE
)

d %>% 
  mutate(json = map(json, ~ fromJSON(.) %>% as.data.frame())) %>% 
  unnest(json)
#>   id user weightmap.P1 weightmap.P2 domains
#> 1  1 xyz1            0          100      a1
#> 2  1 xyz1            0          100      b1
#> 3  2 xyz2          100            0      a2
#> 4  2 xyz2          100            0      b2
  • mutate...正在从字符串转换为嵌套数据框列。
  • unnest...将这些数据框排除在多列
  • 之后

答案 1 :(得分:3)

我会选择 jsonlite 包与 mapply 转换功能和data.table&#39; s一起使用的 rbindlist

$(document).ready(function() {
    var map ;
var infoWindow = new google.maps.InfoWindow({
    disableAutoPan : false,
    maxWidth : 450 ,
    zIndex : 1 
});
function loadMap(){
    var markers = new Array();
    var mapOptions = {
        center : new google.maps.LatLng(34.746481, -92.289595) ,
        zoom : 12 ,
        mapTypeControl: false,
        streetViewControl: false,
        zoomControl: true
    };
    //create map.
    var mapId     = document.getElementById('map');
        map       = new google.maps.Map(mapId, mapOptions);
    console.log(markers)
    //map content creation.
    $('.mapVars').each(function(index, el){
        var address = $(el).find('.address').html(),
            state   = $(el).find('.state').html(),
            country = $(el).find('.country').html(),
            lat     = $(el).find('.lat').html(),
            lng     = $(el).find('.lng').html(),
            content = $(el).find('.content').html(),
            name    = $(el).find('.name').html();
        var fullAdress = address + '<br />' + state ;   
        //marker creation.
        var newMarker = createMarker(lat, lng, name, content, fullAdress);
    });
    //add marker to map.
    function createMarker(lat, lng, name, content, fullAdress){
        //create marker options.
        var marker = new google.maps.Marker({
            position : new google.maps.LatLng(lat, lng) ,
            map : map ,
            animation : google.maps.Animation.DROP,
            clickable : true ,
            title : name,
            zIndex : 1 
        });
        var windowContent = buildHtml(content, name, fullAdress);
        //info window open event.
        google.maps.event.addListener(marker, 'click', function(e){
            infoWindow.close();
            infoWindow.setContent(windowContent);
            infoWindow.open(map, marker);
        }); 
        markers.push(marker);
        return marker ;
    }
    //infoWindow content.
    function buildHtml(content, name, fullAdress){
        html = ' '
        html += '<div class=\"info-window\">';
        html += '<div class=\"upper\">';
        html += '<h5>' + name + '</h5>' + fullAdress;
        html += '</div>' ;
        html += '<div class=\"lower\">' ;
        html += content ;
        html += '</div></div>' ;
        return html ;
    }
    $('.map-trigger').on('click', function(event) {
        event.preventDefault();
        marker = markers[this.id];
        var content = $(this).find('.content').html();
            infoWindow.close();
            infoWindow.setContent(content);
            infoWindow.open(map, marker);
    }); 
}
google.maps.event.addDomListener(window, 'load', loadMap());
});

答案 2 :(得分:2)

无法使flatten参数按预期工作,因此需要取消列表,然后在使用do.call进行rbinding之前“重新列出”:

library(jsonlite)
 do.call( rbind, 
          lapply(raw_df$json, 
                  function(j) as.list(unlist(fromJSON(j, flatten=TRUE)))
        )       )
     user   weightmap.P1 weightmap.P2 domains1 domains2
[1,] "xyz2" "100"        "0"          "a2"     "b2"    
[2,] "xyz1" "0"          "100"        "a1"     "b1"    

不可否认,这将需要进一步处理,因为它强制所有线路都有特色。

答案 3 :(得分:0)

library(jsonlite)
json = c(
        '{"user":"xyz1","weightmap": {"P1":0,"P2":100}, "domains":["a1","b1"]}',
        '{"user":"xyz2","weightmap": {"P1":100,"P2":0}, "domains":["a2","b2"]}'
        )

json <- lapply( paste0("[", json ,"]"), 
                function(x) jsonlite::fromJSON(x))

df <- data.frame(matrix(unlist(json), nrow=2, ncol=5, byrow=T))

df <- df %>% unite(Domains, X4, X5, sep = ", ") 
colnames(df) <- c("user", "P1", "P2", "domains")
head(df)

输出为:

  user  P1  P2 domains
1 xyz1   0 100  a1, b1
2 xyz2 100   0  a2, b2

答案 4 :(得分:0)

使用 tidyjson https://cran.r-project.org/web/packages/tidyjson/vignettes/introduction-to-tidyjson.html

install.packages("tidyjson")

library(tidyjson)

json_as_df <- raw_df$json %>% spread_all

# retain columns
json_as_df <- raw_df %>% as.tbl_json(json.column = "json") %>% spread_all