2012-07-19 20 views
10

यह प्रश्न गैर-चक्रीय सजातीय या विषम डेटा संरचनाओं के किसी भी संग्रह को डेटाफ्रेम में परिवर्तित करने के लिए एक सामान्य तंत्र के बारे में है। यह कई JSON दस्तावेज़ों के इंजेक्शन से निपटने या शब्दकोशों की एक श्रृंखला है जो एक बड़े JSON दस्तावेज़ के साथ विशेष रूप से उपयोगी हो सकता है।आर: जेएसओएन के जेएसओएन की जेनेरिक फ्लैटनिंग डेटा.फ्रेम

वहाँ कई अतः सवाल है कि गहराई से नेस्टेड JSON संरचनाओं से छेड़छाड़ और उन्हें कार्यक्षमता जैसे plyr, lapply, आदि सभी सवाल और जवाब मैं पाया है के रूप में एक सामान्य की पेशकश करने के लिए विरोध विशिष्ट मामलों के बारे में हैं का उपयोग कर dataframes में बदल के साथ सौदा कर रहे हैं जटिल JSON डेटा संरचनाओं के संग्रह से निपटने के लिए दृष्टिकोण।

पायथन और रूबी में मुझे एक सामान्य डेटा संरचना फ़्लैटनिंग उपयोगिता को कार्यान्वित करके अच्छी तरह से सेवा दी गई है जो डेटा संरचना में एक पत्ती नोड के पथ का उपयोग करता है, जो कि उस नोड पर फ़्लैट किए गए डेटा संरचना में मूल्य के नाम के रूप में होता है। उदाहरण के लिए, मान my_data[['x']][[2]][['y']]result[['x.2.y']] के रूप में दिखाई देगा।

यदि किसी के पास इन डेटा संरचनाओं का संग्रह है जो पूरी तरह से समान नहीं हो सकता है तो डेटाफ्रेम में सफल फ़्लैटिंग करने की कुंजी सभी संभावित डेटाफ्रेम कॉलम के नामों की खोज करेगी, उदाहरण के लिए, सभी चाबियों का संघ लेना/व्यक्तिगत रूप से flattened डेटा संरचनाओं में मूल्यों के नाम।

यह एक सामान्य पैटर्न की तरह प्रतीत होता है और इसलिए मैं सोच रहा हूं कि किसी ने पहले ही आर के लिए इसे बनाया है या नहीं, अगर मैं इसे बनाउंगा, लेकिन आर के अद्वितीय वादे-आधारित डेटा संरचनाओं को देखते हुए, मैं सलाह की सराहना करता हूं एक कार्यान्वयन दृष्टिकोण जो ढेर थ्रैशिंग को कम करता है।

+0

हुह? मेरे लिए बहुत अधिक अंग्रेजी (वैसे भी) समझने के लिए। कुछ (संभवतः) धीमी कोड के साथ कुछ प्रतिलिपि इनपुट प्रदान करने का सुझाव दें जो आपके इच्छित आउटपुट का उत्पादन करता है, और वहां से जाता है। शायद यह सिर्फ इतना है कि मैं JSON नहीं जानता। क्या आप एक नए आर सत्र में कुछ पेस्टेबल प्रदान कर सकते हैं जो आपके प्रश्न का प्रदर्शन करने के लिए कहीं से कुछ JSON डेटा डाउनलोड करता है? [एक महान पुनरुत्पादित उदाहरण कैसे बनाएं] (http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) –

उत्तर

7

हाय @Sim कल आपकी समस्या पर चिंतन करने के कारण मैं था परिभाषित:

flatten<-function(x) { 
    dumnames<-unlist(getnames(x,T)) 
    dumnames<-gsub("(*.)\\.1","\\1",dumnames) 
    repeat { 
     x <- do.call(.Primitive("c"), x) 
     if(!any(vapply(x, is.list, logical(1)))){ 
      names(x)<-dumnames 
      return(x) 
     } 
    } 
} 
getnames<-function(x,recursive){ 

    nametree <- function(x, parent_name, depth) { 
     if (length(x) == 0) 
      return(character(0)) 
     x_names <- names(x) 
     if (is.null(x_names)){ 
      x_names <- seq_along(x) 
      x_names <- paste(parent_name, x_names, sep = "") 
     }else{ 
      x_names[x_names==""] <- seq_along(x)[x_names==""] 
      x_names <- paste(parent_name, x_names, sep = "") 
     } 
     if (!is.list(x) || (!recursive && depth >= 1L)) 
      return(x_names) 
     x_names <- paste(x_names, ".", sep = "") 
     lapply(seq_len(length(x)), function(i) nametree(x[[i]], 
      x_names[i], depth + 1L)) 
    } 
    nametree(x, "", 0L) 
} 

(getnames AnnotationDbi से अनुकूलित है ::: make.name.tree)

( flatten यहाँ How to flatten a list to a list without coercion? चर्चा से अनुकूलित है)

एक सरल उदाहरण

my_data<-list(x=list(1,list(1,2,y='e'),3)) 

> my_data[['x']][[2]][['y']] 
[1] "e" 

> out<-flatten(my_data) 
> out 
$x.1 
[1] 1 

$x.2.1 
[1] 1 

$x.2.2 
[1] 2 

$x.2.y 
[1] "e" 

$x.3 
[1] 3 

> out[['x.2.y']] 
[1] "e" 

के रूप में तो परिणाम मोटे तौर पर नामकरण संरचना सुझाव के साथ एक चपटी सूची है। जबरदस्ती से बचा जाता है जो एक प्लस है।

एक अधिक जटिल उदाहरण

library(RJSONIO) 
library(RCurl) 
json.data<-getURL("http://www.reddit.com/r/leagueoflegends/.json") 
dumdata<-fromJSON(json.data) 
out<-flatten(dumdata) 

अद्यतन

अनुभवहीन रास्ता .1

my_data<-list(x=list(1,list(1,2,y='e'),3)) 
gsub("(*.)\\.1","\\1",unlist(getnames(my_data,T))) 

> gsub("(*.)\\.1","\\1",unlist(getnames(my_data,T))) 
[1] "x.1" "x.2.1" "x.2.2" "x.2.y" "x.3" 
+0

आशाजनक लग रहा है। आप कैसे सुझाव देंगे कि हम पीछे की ओर से छुटकारा पाएं '.1'? – Sim

+0

आपको 'नाम (flattened_structure) 'को फिर से सौंपने में सक्षम होना चाहिए, है ना? – Sim

+0

मैं सहमत हूं। अब क्लीनर मेरा सवाल विशेष रूप से एक बड़े JSON दस्तावेज़ को परिवर्तित करने के बारे में था जो डेटा/फ्रेम में शब्दकोशों/हैंश की एक सरणी है। इसके लिए आपको कॉलम सेट को सभी फ़्लैटेड सूची नामों के संघ के रूप में बनाना होगा, है ना? – Sim

4

आर में JSON इनपुट से निपटने के लिए दो पैकेज हैं: rjson और RJSONIO। यदि मैं सही ढंग से समझता हूं कि "गैर-चक्रीय सजातीय या विषम डेटा संरचनाओं का संग्रह" का अर्थ क्या है, तो मुझे लगता है कि इनमें से कोई भी पैकेज list के रूप में उस तरह की संरचना आयात करेगा।

आप unlist फ़ंक्शन का उपयोग करके उस सूची (वेक्टर में) को फ़्लैट कर सकते हैं।

यदि सूची उपयुक्त रूप से संरचित है (एक गैर-नेस्टेड सूची जहां प्रत्येक तत्व एक ही लंबाई है) तो as.data.frame सूची को डेटा फ्रेम के रूप में परिवर्तित करने के लिए एक विकल्प का प्रावधान करता है।

एक उदाहरण:

(my_data <- list(x = list('1' = 1, '2' = list(y = 2)))) 
unlist(my_data) 
+0

डाउनवोट के साथ क्या है? 'अनलिस्ट' बिल्कुल "जेनेरिक डेटा स्ट्रक्चर फ़्लैटिंग यूटिलिटी" की तरह दिखता है जो @ सिम चाहता है। वास्तव में, @ttmaccer द्वारा लिंक किए गए समान प्रश्न में ऐसे उत्तर शामिल हैं जो 'असूचीबद्ध' का व्यापक उपयोग करते हैं। –

+0

@ttmaccer: हाँ, आप आर में दोनों तरीकों से नहीं हो सकते हैं। आप या तो एक फ्लैट प्रकार (वेक्टर) डेटा संरचना एक डेटा प्रकार या मिश्रित प्रकार के साथ घोंसला (सूची) संरचना के साथ। मुझे लगता है कि आर में पर्याप्त उपकरण हैं कि किसी भी जेएसओएन जो कुछ भी आप चाहते हैं उसे बदलने योग्य है। –

+0

@RichieCotton @ttmaccer मैं मानता हूं कि 'असूची' सामान्य रूप से काम नहीं करेगा। यदि यह बॉक्स में से सबसे अच्छा आर है, तो मैं आगे बढ़ूंगा और रिकर्सिव वंश फ्लैटर लिखूंगा जिसका मैंने अन्य भाषाओं में उपयोग किया है। – Sim

1

अनुगामी jsonlite पैकेज RJSONIO का एक कांटा विशेष रूप से JSON और के बीच रूपांतरण बनाने के लिए डिज़ाइन किया गया है दूर करने के लिए डेटा फ्रेम आसान है। आप कोई उदाहरण json डेटा प्रदान नहीं करते हैं, लेकिन मुझे लगता है कि यह वही हो सकता है जो आप खोज रहे हैं। इस blog post या the vignette पर एक नज़र डालें।

0

फ़्लैटन और getnames कार्यों के साथ महान जवाब। JSON तारों के वेक्टर से डेटा.फ्रेम पर प्राप्त करने के लिए आवश्यक सभी विकल्पों को जानने के लिए कुछ मिनट लग गए, इसलिए मैंने सोचा कि मैं इसे यहां रिकॉर्ड करूंगा। मान लीजिए जेसनवेक JSON तारों का एक वेक्टर है। निम्नलिखित डेटा.फ्रेम (डेटाटेबल) बनाता है जहां प्रति पंक्ति एक पंक्ति होती है, और प्रत्येक कॉलम JSON पेड़ के एक अलग संभावित पत्ता नोड से मेल खाता है। कोई भी स्ट्रिंग गायब कोई विशेष पत्ता नोड एनए से भरा होता है।

library(data.table) 
library(jsonlite) 
parsed = lapply(jsonvec, fromJSON, simplifyVector=FALSE) 
flattened = lapply(parsed, flatten) #using flatten from accepted answer 
d = rbindlist(flattened, fill=TRUE) 
संबंधित मुद्दे