2013-06-05 91 views
28

Tôi có tệp chứa hơn 1500 đối tượng json mà tôi muốn làm việc với R. Tôi có thể nhập dữ liệu dưới dạng danh sách, nhưng gặp sự cố khi nén dữ liệu vào cấu trúc hữu ích. Tôi muốn tạo một khung dữ liệu chứa một hàng cho mỗi đối tượng json và một cột cho mỗi cặp khóa: value.Nhập dữ liệu json đã nhập vào khung dữ liệu

tôi đã tái tạo hoàn cảnh của tôi với nhỏ, giả bộ dữ liệu này:

[{"name":"Doe, John","group":"Red","age (y)":24,"height (cm)":182,"wieght (kg)":74.8,"score":null}, 
{"name":"Doe, Jane","group":"Green","age (y)":30,"height (cm)":170,"wieght (kg)":70.1,"score":500}, 
{"name":"Smith, Joan","group":"Yellow","age (y)":41,"height (cm)":169,"wieght (kg)":60,"score":null}, 
{"name":"Brown, Sam","group":"Green","age (y)":22,"height (cm)":183,"wieght (kg)":75,"score":865}, 
{"name":"Jones, Larry","group":"Green","age (y)":31,"height (cm)":178,"wieght (kg)":83.9,"score":221}, 
{"name":"Murray, Seth","group":"Red","age (y)":35,"height (cm)":172,"wieght (kg)":76.2,"score":413}, 
{"name":"Doe, Jane","group":"Yellow","age (y)":22,"height (cm)":164,"wieght (kg)":68,"score":902}] 

Một số tính năng của dữ liệu:

  • Các đối tượng tất cả đều chứa cùng một số chính: cặp giá trị mặc dù một số giá trị là null
  • Có hai cột không phải là số cho mỗi đối tượng (tên và nhóm)
  • tên là số nhận dạng duy nhất ier, có 10 hoặc nhiều nhóm
  • nhiều tên và nhóm entires chứa dấu cách, dấu phẩy và dấu chấm câu khác.

Dựa trên câu hỏi này: R list(structure(list())) to data frame, tôi thử như sau:

json_file <- "test.json" 
json_data <- fromJSON(json_file) 
asFrame <- do.call("rbind.fill", lapply(json_data, as.data.frame)) 

Với cả hai dữ liệu thực tế và dữ liệu giả mạo này, dòng cuối cùng cho tôi lỗi này:

Error in data.frame(name = "Doe, John", group = "Red", `age (y)` = 24, : 
    arguments imply differing number of rows: 1, 0 

Trả lời

38

Bạn chỉ cần thay thế số NULL của bạn bằng NA:

require(RJSONIO)  

json_file <- '[{"name":"Doe, John","group":"Red","age (y)":24,"height (cm)":182,"wieght (kg)":74.8,"score":null}, 
    {"name":"Doe, Jane","group":"Green","age (y)":30,"height (cm)":170,"wieght (kg)":70.1,"score":500}, 
    {"name":"Smith, Joan","group":"Yellow","age (y)":41,"height (cm)":169,"wieght (kg)":60,"score":null}, 
    {"name":"Brown, Sam","group":"Green","age (y)":22,"height (cm)":183,"wieght (kg)":75,"score":865}, 
    {"name":"Jones, Larry","group":"Green","age (y)":31,"height (cm)":178,"wieght (kg)":83.9,"score":221}, 
    {"name":"Murray, Seth","group":"Red","age (y)":35,"height (cm)":172,"wieght (kg)":76.2,"score":413}, 
    {"name":"Doe, Jane","group":"Yellow","age (y)":22,"height (cm)":164,"wieght (kg)":68,"score":902}]' 


json_file <- fromJSON(json_file) 

json_file <- lapply(json_file, function(x) { 
    x[sapply(x, is.null)] <- NA 
    unlist(x) 
}) 

Một khi bạn có một giá trị không null cho mỗi phần tử, bạn có thể gọi rbind mà không nhận được một lỗi:

do.call("rbind", json_file) 
    name   group age (y) height (cm) wieght (kg) score 
[1,] "Doe, John" "Red" "24" "182"  "74.8"  NA 
[2,] "Doe, Jane" "Green" "30" "170"  "70.1"  "500" 
[3,] "Smith, Joan" "Yellow" "41" "169"  "60"  NA 
[4,] "Brown, Sam" "Green" "22" "183"  "75"  "865" 
[5,] "Jones, Larry" "Green" "31" "178"  "83.9"  "221" 
[6,] "Murray, Seth" "Red" "35" "172"  "76.2"  "413" 
[7,] "Doe, Jane" "Yellow" "22" "164"  "68"  "902" 
+3

Tôi ngạc nhiên là không có chức năng tốt hơn để làm điều này. (đối với XML có các hàm như XMLtoDataFrame) nên JSONtoDataFrame sẽ là tuyệt vời – userJT

+1

@userJT - có 'jsonlite :: fromJSON' - xử lý các NULL và đơn giản hóa thành' data.frame'. Xem [câu trả lời của tôi] (http://stackoverflow.com/a/37739735/5977215) – SymbolixAU

+0

điều này chuyển đổi json_file thành ma trận, không phải là một khung dữ liệu. Làm thế nào để có được một data.frame? – TSR

-2

Để loại bỏ các giá trị null sử dụng tham số nullValue

json_data <- fromJSON(json_file, nullValue = NA) 
asFrame <- do.call("rbind.fill", lapply(json_data, as.data.frame)) 

cách này có thể won't bất kỳ trích dẫn không cần thiết nào trong đầu ra của bạn

2
dplyr::bind_rows(fromJSON(file_name)) 
+0

mà bạn đang sử dụng hàm 'fromJson' nào? Nếu nó từ 'jsonlite', thì' dplyr :: bind_rows' là thừa. Nếu nó từ 'rjson' thì lỗi solutino của bạn trên dữ liệu được cung cấp. – SymbolixAU

+0

không nhớ; mọi thứ phải thay đổi –

15

Điều này rất đơn giản nếu bạn sử dụng library(jsonlite) và chức năng fromJSON. Nó cũng xử lý các giá trị null và chuyển đổi chúng thành NA.

json_file <- '[{"name":"Doe, John","group":"Red","age (y)":24,"height (cm)":182,"wieght (kg)":74.8,"score":null}, 
    {"name":"Doe, Jane","group":"Green","age (y)":30,"height (cm)":170,"wieght (kg)":70.1,"score":500}, 
{"name":"Smith, Joan","group":"Yellow","age (y)":41,"height (cm)":169,"wieght (kg)":60,"score":null}, 
{"name":"Brown, Sam","group":"Green","age (y)":22,"height (cm)":183,"wieght (kg)":75,"score":865}, 
{"name":"Jones, Larry","group":"Green","age (y)":31,"height (cm)":178,"wieght (kg)":83.9,"score":221}, 
{"name":"Murray, Seth","group":"Red","age (y)":35,"height (cm)":172,"wieght (kg)":76.2,"score":413}, 
{"name":"Doe, Jane","group":"Yellow","age (y)":22,"height (cm)":164,"wieght (kg)":68,"score":902}]' 

library(jsonlite) 
fromJSON(json_file) 
#   name group age (y) height (cm) wieght (kg) score 
# 1 Doe, John Red  24   182  74.8 NA 
# 2 Doe, Jane Green  30   170  70.1 500 
# 3 Smith, Joan Yellow  41   169  60.0 NA 
# 4 Brown, Sam Green  22   183  75.0 865 
# 5 Jones, Larry Green  31   178  83.9 221 
# 6 Murray, Seth Red  35   172  76.2 413 
# 7 Doe, Jane Yellow  22   164  68.0 902 

str(fromJSON(json_file)) 
# 'data.frame': 7 obs. of 6 variables: 
# $ name  : chr "Doe, John" "Doe, Jane" "Smith, Joan" "Brown, Sam" ... 
# $ group  : chr "Red" "Green" "Yellow" "Green" ... 
# $ age (y) : int 24 30 41 22 31 35 22 
# $ height (cm): int 182 170 169 183 178 172 164 
# $ wieght (kg): num 74.8 70.1 60 75 83.9 76.2 68 
# $ score  : int NA 500 NA 865 221 413 902 
+0

Tôi chạy chính xác mã giống như bạn, nhưng khi tôi chạy 'fromJSON' nó trả về một danh sách, không phải là một khung dữ liệu. Làm thế nào bạn có được nó để trả về một khung dữ liệu? – Alexander

+0

@Alexander - Tôi vẫn nhận được 'data.frame'. Đảm bảo bạn đang sử dụng 'jsonlite :: fromJSON' – SymbolixAU

3
library(rjson) 
Lines <- readLines("yelp_academic_dataset_business.json") 
business <- as.data.frame(t(sapply(Lines, fromJSON))) 

Bạn có thể thử này để nạp dữ liệu JSON vào R

Các vấn đề liên quan