2017-02-26 9 views
6

यह पिछली पोस्ट (Interactively adding points to plotly R without redrawing background plot) की निरंतरता है। मैं 32 mtcars डेटासेट मानों के एक स्कैटरप्लॉट मैट्रिक्स (आर पैकेज ggpairs का उपयोग कर) बना रहा हूँ। मेरा लक्ष्य उपयोगकर्ताओं को किसी सबप्लॉट में किसी बिंदु पर क्लिक करने की अनुमति देना है। यह एक यादृच्छिक सबसेट (आकार भिन्न हो सकता है, लेकिन नीचे दिए गए उदाहरण में 2) सभी डेटा स्कैटरप्लॉट सबप्लॉट्स में ओवरलैड होने के लिए मूल डेटा फ्रेम से पंक्तियों का है (स्कैटरप्लॉट की संख्या भिन्न हो सकती है, लेकिन नीचे दिए गए उदाहरण में 3 है)।पृष्ठभूमि साजिश को पुनर्निर्मित किए बिना साजिश आर में साप्ताहिक रूप से अंक जोड़ना

मेरे अर्द्ध काम कर मेगावाट इस प्रकार है -

library(plotly) 
library(htmlwidgets) 
library(GGally) 

dat <- mtcars[,c(3,4,7)] 
dat[,3] = dat[,3]*8 

p <- ggpairs(dat) 

myMax = max(abs(dat)) 
myMin = min(abs(dat)) 
myRange = c(myMax, myMin) 

p2 <- p 
for(x in 2:p$nrow) { 
    for(y in 1:(x-1)) { 
    p2[x,y] <- p[x,y] + 
     coord_cartesian(xlim = c(myRange), ylim = c(myRange)) 
    } 
} 

p3 <- ggplotly(p2) 

p3 %>% onRender("function(el, x, data) { 

    // Number of rows in data frame is myLength=3 
    myLength = Math.sqrt(document.getElementsByClassName('cartesianlayer')[0].childNodes.length); 

    // AxisNames stores the names of the 3 rows ('disp','hp','qsec') 
    AxisNames = []; 
    for (i = 1; i < (myLength+1); i++) { 
     AxisNames.push(document.getElementsByClassName('infolayer')[0].childNodes[i].textContent); 
    } 

    el.on('plotly_click', function(e) { 
     // Grab two random rows of the 32 rows from mtcars dataset and store in myData. In my real code (not this MWE), myData represents an array of 1 or more objects, where each object contains values for each column in the dataset. 
     data1 = data[Math.floor(Math.random() * 32) + 1]; 
     data2 = data[Math.floor(Math.random() * 32) + 1]; 
     var myData = [data1, data2]; 

     //May not be necessary, but this creates one array allData that contains all column values for all randomly selected rows. Since this example has 3 columns (disp, hp, and qsec) and two randomly selected rows, allData has a length of 6. 
     var allData = []; 
     for (i = 0; i < myData.length; i++){ 
     for (j = 0 ; j < myLength; j++){ 
      allData.push(myData[i][AxisNames[j]]) 
     } 
     } 
     console.log(allData) 

     //This correctly plots the disp on the x-axis and qsec on the y-axis of both randomly selected data frame rows and plots it into the correct scatterplot (bottom left one that has x-axis of disp and y-axis of qsec). This needs to be automated, so that the corresponding x and y values for the 2 randomly selected data frame rows are also plotted on all other scatterplot matrices. 
     var trace1 = { 
     x: [allData[0], allData[3]], 
     y: [allData[2], allData[5]], 
     mode: 'markers', 
     marker: { 
     color: 'green', 
     size: 20 
     } 
     }; 

     Plotly.addTraces(el.id, trace1); 
     } 
    )}", data = dat) 

क्या वर्तमान में होता है बेतरतीब ढंग से चुनी हुई पंक्तियां केवल बजाय तीनों scatterplots में के तल में एक subplot में (हरे रंग में) साजिश रची है छोड़ दिया (है)। मैं नीचे बाईं ओर के बगल में किसी भी अन्य स्कैटरप्लॉट पर मुश्किल से पहुंच और साजिश कर रहा हूं।

ScatMatrix

मैं और व्यापक डेटा फ्रेम (पंक्ति टिप्पणियों के हजारों के आदेश पर) एक बहुत लंबे समय तक डेटा फ्रेम के साथ विधि पर काम किया जा सकता है (तीन से अधिक कॉलम, तीन से अधिक scatterplots के कारण तैयार हो)। इसलिए, मैं इस लक्ष्य को प्राप्त करने के लिए एक प्रभावी तरीका खोजने की कोशिश कर रहा हूं ताकि अंक आकर्षित करने में बहुत लंबा समय न लगे। मुझे विश्वास है (पढ़ने से) कि प्रत्येक plotly.addTraces() साजिश समय धीमा कर सकते हैं। यदि डेटा फ्रेम में, 6 कॉलम थे, तो 15 स्कैटरप्लॉट होंगे, और यदि प्रत्येक स्कैटरप्लॉट के अपने स्वयं के addTraces() थे, तो 15 addTraces() होंगे। मुझे आश्चर्य है कि क्या यह अंक की साजिश को बहुत धीमा कर देगा? यदि ऐसा है, तो मैं इस लक्ष्य को सबसे कुशलता से प्राप्त करने के बारे में सलाह सुनने के लिए बहुत उत्सुक हूं (सभी स्कैटरप्लॉट पर जितनी जल्दी हो सके हरे रंग के बिंदुओं को प्लॉट करने की इजाजत देता है)।

मैं किसी भी मदद या विचारों के लिए सबसे आभारी हूं!

संपादित करें:

अच्छा से इनपुट के लिए धन्यवाद, मैं इस स्क्रिप्ट अद्यतन करने के लिए इतना है कि यह प्रत्येक subplot में प्रयोग की जाने वाली अक्ष लेबल और चर हार्डकोड करने की जरूरत नहीं है में सक्षम था। अद्यतन मेगावाट के नीचे है:

library(plotly) 
library(htmlwidgets) 
library(GGally) 

dat <- mtcars[,c(3,4,7)] 
dat[,3] = dat[,3]*8 

p <- ggpairs(dat) 

myMax = max(abs(dat)) 
myMin = min(abs(dat)) 
myRange = c(myMax, myMin) 

p2 <- p 
for(x in 2:p$nrow) { 
    for(y in 1:(x-1)) { 
    p2[x,y] <- p[x,y] + 
     coord_cartesian(xlim = c(myRange), ylim = c(myRange)) 
    } 
} 

p3 <- ggplotly(p2) 

p3 %>% onRender("function(el, x, data) { 

       len = Math.sqrt(document.getElementsByClassName('cartesianlayer')[0].childNodes.length); 

       // AxisNames stores the names of the 3 rows ('disp','hp','qsec') 
       AxisNames = []; 
       for (i = 1; i < (len+1); i++) { 
       AxisNames.push(document.getElementsByClassName('infolayer')[0].childNodes[i].textContent); 
       } 

       el.on('plotly_click', function(e) { 
        data1 = data[Math.floor(Math.random() * 32) + 1]; 
        data2 = data[Math.floor(Math.random() * 32) + 1]; 
        var myData = [data1, data2]; 
        console.log(myData); 

        var Traces = []; 
        var i=0; 
        var k=1; 
        while ((i*len+k)<=Math.pow((len-1),2)) { 
         var xArr = []; 
         for (a=0; a<myData.length; a++){ 
          xArr.push(myData[a][AxisNames[i]]) 
         } 
        while ((i+k)<len){ 
         var yArr = []; 
         for (a=0; a<myData.length; a++){ 
          yArr.push(myData[a][AxisNames[(len-k)]]) 
         } 

         var trace = { 
         x: xArr, 
         y: yArr, 
         mode: 'markers', 
         marker: { 
          color: 'green', 
          size: 20 
         }, 
         xaxis: 'x' + (i+1), 
         yaxis: 'y' + (i*len+k) 
         }; 
         Traces.push(trace); 
         k++; 
        } 
        i++; 
        k=1; 
        } 
        Plotly.addTraces(el.id, Traces); 
       } 
       )}", data = dat) 

उत्तर

1

आप जोड़े जाने के लिए जो साजिश का पता लगाने की जरूरत है के लिए निर्दिष्ट करने के लिए अपने निशान के लिए एक xaxis और yaxis जोड़ सकते हैं।

आपके मामले में, पहले कॉलम के लिए xaxisx है, दूसरा x2, और तीसरे है। नीचे बाईं ओर साजिश के yaxisy है और यह ऊपर, y2 एक के लिए ऊपर y3 पहले कॉलम के शीर्ष एक है, तो मध्य स्तम्भ नीचे साजिश आदि के लिए y4 के लिए जा रहा बढ़ जाती है, ...

उदाहरण के लिए , आप कर सकते हैं, आपके onRender:

var trace1 = { 
    x: [myData[0]['disp'], myData[1]['disp']], 
    y: [myData[0]['qsec'], myData[0]['qsec']], 
    mode: 'markers', 
    marker: { 
    color: 'green', 
    size: 20 
    }, 
    xaxis: 'x', 
    yaxis: 'y' 
}; 

var trace2 = { 
    x: [myData[0]['disp'], myData[1]['disp']], 
    y: [myData[0]['hp'], myData[0]['hp']], 
    mode: 'markers', 
    marker: { 
    color: 'green', 
    size: 20 
    }, 
    xaxis: 'x', 
    yaxis: 'y2' 
}; 

var trace3 = { 
    x: [myData[0]['hp'], myData[0]['hp']], 
    y: [myData[0]['qsec'], myData[0]['qsec']], 
    mode: 'markers', 
    marker: { 
    color: 'green', 
    size: 20 
    }, 
    xaxis: 'x2', 
    yaxis: 'y4' 
}; 

Plotly.addTraces(el.id, [trace1,trace2,trace3]); 
संबंधित मुद्दे