2010-10-20 13 views
28

से 3 डी सतह प्लॉट करना मेरे पास 3 कॉलम मैट्रिक्स
x, y, z है जहां z x और y का फ़ंक्शन है।आर: x, y, z

मैं जानता हूँ कि plot3d(x,y,z)

के साथ इन बिंदुओं में से एक "बिखराव साजिश" साजिश करने के लिए कैसे लेकिन अगर मैं एक सतह चाहते बजाय मैं ऐसे surface3d के रूप में समस्या यह है कि इसे स्वीकार नहीं करता है अन्य आदेशों का उपयोग करना चाहिए plot3d रूप में एक ही आदानों यह

(nº elements of z) = (n of elements of x) * (n of elements of x) 

के साथ एक मैट्रिक्स की जरूरत के लिए मैं इस मैट्रिक्स कैसे प्राप्त कर सकता है? मैंने कमांड इंटरप के साथ प्रयास किया है, जैसा कि मुझे करता है जब मुझे समोच्च भूखंडों का उपयोग करने की आवश्यकता होती है।

मैं इस मैट्रिक्स की गणना किए बिना x, y, z से सीधे सतह को कैसे प्लॉट कर सकता हूं? यदि मेरे पास बहुत अधिक अंक थे तो यह मैट्रिक्स बहुत बड़ा होगा।

चियर्स

+1

जहां plot3d आता है ??? आप किस पैकेज का उपयोग कर रहे हैं? –

+0

आरजीएल, लेकिन मैं – skan

उत्तर

6

आप समारोह outer() का उपयोग यह उत्पन्न करने के लिए कर सकते हैं।

फ़ंक्शन persp() फ़ंक्शन के लिए डेमो पर नज़र डालें, जो सतहों के लिए परिप्रेक्ष्य प्लॉट आकर्षित करने के लिए आधार ग्राफिक्स फ़ंक्शन है।

x <- seq(-10, 10, length.out = 50) 
y <- x 
rotsinc <- function(x,y) { 
    sinc <- function(x) { y <- sin(x)/x ; y[is.na(y)] <- 1; y } 
    10 * sinc(sqrt(x^2+y^2)) 
} 

z <- outer(x, y, rotsinc) 
persp(x, y, z) 

ही surface3d() पर लागू होता है:

यहाँ अपने पहले उदाहरण है

require(rgl) 
surface3d(x, y, z) 
+3

हाय का सुझाव दे सकता हूं। मेरे पास एक स्पष्ट कार्य नहीं है। मेरा डेटा किसी अन्य प्रोग्राम से निर्यात किया जाता है, एक जटिल अनुकूलन से आते हैं, हम कह सकते हैं कि वे एक ब्लैक बॉक्स से आते हैं। मेरे पास एक्स, वाई और जेड है लेकिन मेरे पास अन्य एक्स और वाई संयोजनों के लिए ज़ेड के अन्य मानों की गणना करने का कोई मतलब नहीं है। – skan

26

अपने x और y coords एक ग्रिड पर तो नहीं कर रहे हैं आप अपने एक्स, वाई अंतर्वेशन करने की जरूरत है , एक सतह पर जेड सतह। आप इसे भूगर्भीय पैकेजों (geoR, gstat, अन्य) या व्यस्त तकनीक जैसे सरल तकनीकों का उपयोग करके क्रिगिंग के साथ कर सकते हैं।

मैं अनुमान लगा रहा हूं कि आपके द्वारा उल्लेख किया गया 'इंटरप' फ़ंक्शन अकिमा पैकेज से है। ध्यान दें कि आउटपुट मैट्रिक्स आपके इनपुट बिंदुओं के आकार से स्वतंत्र है। आपके इनपुट में 10000 अंक हो सकते हैं और यदि आप चाहें तो 10x10 ग्रिड पर इंटरपोलेट कर सकते हैं। डिफ़ॉल्ट Akima करके :: interp एक 40x40 ग्रिड पर यह होता है:

> require(akima) ; require(rgl) 
> x=runif(1000) 
> y=runif(1000) 
> z=rnorm(1000) 
> s=interp(x,y,z) 
> dim(s$z) 
[1] 40 40 
> surface3d(s$x,s$y,s$z) 

कि काँटेदार और बकवास है क्योंकि इसके यादृच्छिक डेटा पर ध्यान देंगे। उम्मीद है कि आपका डेटा नहीं है!

+1

हाय। यही वह था जो मैंने कभी-कभी किया लेकिन कभी-कभी यह काम नहीं करता है। आपके उदाहरण में उदाहरण उदाहरण इंटरप का उपयोग करते समय मुझे कई एनएएस मिलते हैं। – skan

+2

समस्या यह है कि यदि मेरे बिंदु collinear – skan

+1

हैं तो मैं interp काम नहीं करता है मैं इसे misc3d parametric3d या अन्य फ़ंक्शन के साथ कैसे कर सकता हूं? – skan

5

rgl बहुत अच्छा है, लेकिन धुरी को सही करने के लिए थोड़ा सा प्रयोग लेता है।

यदि आपके पास बहुत सारे अंक हैं, तो उनसे यादृच्छिक नमूना क्यों न लें, और फिर परिणामी सतह को प्लॉट करें। नमूनाकरण की प्रक्रिया आपके डेटा को बहुत प्रभावित कर रही है या नहीं, यह देखने के लिए आप एक ही डेटा से नमूने के आधार पर कई सतहों को जोड़ सकते हैं।

तो, यहां एक बहुत ही भयानक कार्य है, लेकिन ऐसा लगता है कि मुझे लगता है कि आप इसे करना चाहते हैं (लेकिन नमूना के बिना)। एक मैट्रिक्स (एक्स, वाई, जेड) को देखते हुए जहां ज़ेड ऊंचाई है, यह दोनों बिंदुओं और सतह दोनों को भी प्लॉट करेगा। सीमाएं हैं कि प्रत्येक (एक्स, वाई) जोड़ी के लिए केवल एक जेड हो सकता है। तो विमान जो खुद पर लूप वापस समस्याओं का कारण बन जाएगा।

plot_points = T सतह से बने व्यक्तिगत बिंदुओं को प्लॉट करेगा - यह जांचने के लिए उपयोगी है कि सतह और अंक वास्तव में मिलते हैं। plot_contour = T 3 डी विज़ुअलाइजेशन के नीचे 2 डी समोच्च साजिश प्लॉट करेगा। सुंदर रंग देने के लिए rainbow पर रंग सेट करें, और कुछ भी इसे भूरे रंग में सेट करेगा, लेकिन फिर आप कस्टम पैलेट देने के लिए फ़ंक्शन को बदल सकते हैं। यह वैसे भी मेरे लिए चाल है, लेकिन मुझे यकीन है कि इसे साफ और अनुकूलित किया जा सकता है। verbose = T बहुत सारे आउटपुट को प्रिंट करता है जिसे मैं फ़ंक्शन को डीबग करने के लिए उपयोग करता हूं और जब यह टूट जाता है।

plot_rgl_model_a <- function(fdata, plot_contour = T, plot_points = T, 
          verbose = F, colour = "rainbow", smoother = F){ 
    ## takes a model in long form, in the format 
    ## 1st column x 
    ## 2nd is y, 
    ## 3rd is z (height) 
    ## and draws an rgl model 

    ## includes a contour plot below and plots the points in blue 
    ## if these are set to TRUE 

    # note that x has to be ascending, followed by y 
    if (verbose) print(head(fdata)) 

    fdata <- fdata[order(fdata[, 1], fdata[, 2]), ] 
    if (verbose) print(head(fdata)) 
    ## 
    require(reshape2) 
    require(rgl) 
    orig_names <- colnames(fdata) 
    colnames(fdata) <- c("x", "y", "z") 
    fdata <- as.data.frame(fdata) 

    ## work out the min and max of x,y,z 
    xlimits <- c(min(fdata$x, na.rm = T), max(fdata$x, na.rm = T)) 
    ylimits <- c(min(fdata$y, na.rm = T), max(fdata$y, na.rm = T)) 
    zlimits <- c(min(fdata$z, na.rm = T), max(fdata$z, na.rm = T)) 
    l <- list (x = xlimits, y = ylimits, z = zlimits) 
    xyz <- do.call(expand.grid, l) 
    if (verbose) print(xyz) 
    x_boundaries <- xyz$x 
    if (verbose) print(class(xyz$x)) 
    y_boundaries <- xyz$y 
    if (verbose) print(class(xyz$y)) 
    z_boundaries <- xyz$z 
    if (verbose) print(class(xyz$z)) 
    if (verbose) print(paste(x_boundaries, y_boundaries, z_boundaries, sep = ";")) 

    # now turn fdata into a wide format for use with the rgl.surface 
    fdata[, 2] <- as.character(fdata[, 2]) 
    fdata[, 3] <- as.character(fdata[, 3]) 
    #if (verbose) print(class(fdata[, 2])) 
    wide_form <- dcast(fdata, y ~ x, value_var = "z") 
    if (verbose) print(head(wide_form)) 
    wide_form_values <- as.matrix(wide_form[, 2:ncol(wide_form)]) 
    if (verbose) print(wide_form_values) 
    x_values <- as.numeric(colnames(wide_form[2:ncol(wide_form)])) 
    y_values <- as.numeric(wide_form[, 1]) 
    if (verbose) print(x_values) 
    if (verbose) print(y_values) 
    wide_form_values <- wide_form_values[order(y_values), order(x_values)] 
    wide_form_values <- as.numeric(wide_form_values) 
    x_values <- x_values[order(x_values)] 
    y_values <- y_values[order(y_values)] 
    if (verbose) print(x_values) 
    if (verbose) print(y_values) 

    if (verbose) print(dim(wide_form_values)) 
    if (verbose) print(length(x_values)) 
    if (verbose) print(length(y_values)) 

    zlim <- range(wide_form_values) 
    if (verbose) print(zlim) 
    zlen <- zlim[2] - zlim[1] + 1 
    if (verbose) print(zlen) 

    if (colour == "rainbow"){ 
    colourut <- rainbow(zlen, alpha = 0) 
    if (verbose) print(colourut) 
    col <- colourut[ wide_form_values - zlim[1] + 1] 
    # if (verbose) print(col) 
    } else { 
    col <- "grey" 
    if (verbose) print(table(col2)) 
    } 


    open3d() 
    plot3d(x_boundaries, y_boundaries, z_boundaries, 
     box = T, col = "black", xlab = orig_names[1], 
     ylab = orig_names[2], zlab = orig_names[3]) 

    rgl.surface(z = x_values, ## these are all different because 
       x = y_values, ## of the confusing way that 
       y = wide_form_values, ## rgl.surface works! - y is the height! 
       coords = c(2,3,1), 
       color = col, 
       alpha = 1.0, 
       lit = F, 
       smooth = smoother) 

    if (plot_points){ 
    # plot points in red just to be on the safe side! 
    points3d(fdata, col = "blue") 
    } 

    if (plot_contour){ 
    # plot the plane underneath 
    flat_matrix <- wide_form_values 
    if (verbose) print(flat_matrix) 
    y_intercept <- (zlim[2] - zlim[1]) * (-2/3) # put the flat matrix 1/2 the distance below the lower height 
    flat_matrix[which(flat_matrix != y_intercept)] <- y_intercept 
    if (verbose) print(flat_matrix) 

    rgl.surface(z = x_values, ## these are all different because 
       x = y_values, ## of the confusing way that 
       y = flat_matrix, ## rgl.surface works! - y is the height! 
       coords = c(2,3,1), 
       color = col, 
       alpha = 1.0, 
       smooth = smoother) 
    } 
} 

add_rgl_model विकल्प के बिना ही काम करता है, लेकिन मौजूदा 3dplot पर एक सतह overlays।

add_rgl_model <- function(fdata){ 

    ## takes a model in long form, in the format 
    ## 1st column x 
    ## 2nd is y, 
    ## 3rd is z (height) 
    ## and draws an rgl model 

    ## 
    # note that x has to be ascending, followed by y 
    print(head(fdata)) 

    fdata <- fdata[order(fdata[, 1], fdata[, 2]), ] 

    print(head(fdata)) 
    ## 
    require(reshape2) 
    require(rgl) 
    orig_names <- colnames(fdata) 

    #print(head(fdata)) 
    colnames(fdata) <- c("x", "y", "z") 
    fdata <- as.data.frame(fdata) 

    ## work out the min and max of x,y,z 
    xlimits <- c(min(fdata$x, na.rm = T), max(fdata$x, na.rm = T)) 
    ylimits <- c(min(fdata$y, na.rm = T), max(fdata$y, na.rm = T)) 
    zlimits <- c(min(fdata$z, na.rm = T), max(fdata$z, na.rm = T)) 
    l <- list (x = xlimits, y = ylimits, z = zlimits) 
    xyz <- do.call(expand.grid, l) 
    #print(xyz) 
    x_boundaries <- xyz$x 
    #print(class(xyz$x)) 
    y_boundaries <- xyz$y 
    #print(class(xyz$y)) 
    z_boundaries <- xyz$z 
    #print(class(xyz$z)) 

    # now turn fdata into a wide format for use with the rgl.surface 
    fdata[, 2] <- as.character(fdata[, 2]) 
    fdata[, 3] <- as.character(fdata[, 3]) 
    #print(class(fdata[, 2])) 
    wide_form <- dcast(fdata, y ~ x, value_var = "z") 
    print(head(wide_form)) 
    wide_form_values <- as.matrix(wide_form[, 2:ncol(wide_form)]) 
    x_values <- as.numeric(colnames(wide_form[2:ncol(wide_form)])) 
    y_values <- as.numeric(wide_form[, 1]) 
    print(x_values) 
    print(y_values) 
    wide_form_values <- wide_form_values[order(y_values), order(x_values)] 
    x_values <- x_values[order(x_values)] 
    y_values <- y_values[order(y_values)] 
    print(x_values) 
    print(y_values) 

    print(dim(wide_form_values)) 
    print(length(x_values)) 
    print(length(y_values)) 

    rgl.surface(z = x_values, ## these are all different because 
       x = y_values, ## of the confusing way that 
       y = wide_form_values, ## rgl.surface works! 
       coords = c(2,3,1), 
       alpha = .8) 
    # plot points in red just to be on the safe side! 
    points3d(fdata, col = "red") 
} 

तो मेरी दृष्टिकोण करने के लिए, अपने सभी डेटा (मैं आसानी से ~ 15k अंक से उत्पन्न सतहों साजिश) के साथ यह करने की कोशिश की जाएगी। यदि यह काम नहीं करता है, तो इन कार्यों का उपयोग करके कई छोटे नमूने लें और उन्हें एक साथ प्लॉट करें।

5

आप जाटिस का उपयोग कर देख सकते हैं। इस उदाहरण में मैंने एक ग्रिड परिभाषित किया है जिस पर मैं z ~ x, y प्लॉट करना चाहता हूं। ऐसा कुछ दिखता है। ध्यान दें कि अधिकांश कोड सिर्फ 3 डी आकार का निर्माण कर रहा है जिसे मैं वायरफ्रेम फ़ंक्शन का उपयोग करके साजिश करता हूं।

चर "बी" और "एस" एक्स या वाई हो सकता है।

require(lattice) 

# begin generating my 3D shape 
b <- seq(from=0, to=20,by=0.5) 
s <- seq(from=0, to=20,by=0.5) 
payoff <- expand.grid(b=b,s=s) 
payoff$payoff <- payoff$b - payoff$s 
payoff$payoff[payoff$payoff < -1] <- -1 
# end generating my 3D shape 


wireframe(payoff ~ s * b, payoff, shade = TRUE, aspect = c(1, 1), 
    light.source = c(10,10,10), main = "Study 1", 
    scales = list(z.ticks=5,arrows=FALSE, col="black", font=10, tck=0.5), 
    screen = list(z = 40, x = -75, y = 0)) 
3

हो सकता है कि अब लेकिन Spacedman निम्नलिखित देर हो चुकी है, तो आप डुप्लिकेट की कोशिश = "पट्टी" या किसी अन्य विकल्प था?

x=runif(1000) 
y=runif(1000) 
z=rnorm(1000) 
s=interp(x,y,z,duplicate="strip") 
surface3d(s$x,s$y,s$z,color="blue") 
points3d(s)