2015-05-22 41 views
8

Tôi có dữ liệu chuỗi thời gian csv cho một số trang web mà tôi tạo ggplots, hiển thị thay đổi trong phương tiện bằng cách sử dụng gói thay đổi. Tôi đã viết một hàm nhận csv, thực hiện một số phép tính để có được các phương tiện sau đó lặp qua các trang web tạo ra một âm mưu cho mỗi. Vấn đề của tôi là một đối tượng được tạo trong vòng lặp for không được tìm thấy.Đối tượng được tạo bên trong hàm không tìm thấy bởi ggplot

Một ví dụ rất đơn giản dưới nhưng tạo ra các lỗi tương tự:

df1 <- data.frame(date = seq(as.Date("2015-01-01"), as.Date("2015-01-10"), 
         by = "day"), 
       site1 = runif(10), 
       site2 = runif(10), 
       site3 = runif(10)) 

example <- function(df1){ 

    sname <- names(df1)[-1] 

    for (i in 1:length(sname)){ 
      df2 <- df1[,c(1, 1+i)] 
      df2$label <- factor(rep("ts", by=length(df2[,1]))) 

      plot <- ggplot()+ 
        geom_point(data=df2, aes(x=date, y=df2[,2]))+ 
        geom_line(data=df2, aes(x=date, y=df2[,2])) 
      sname.i<-sname[i] 
      filename<-paste0(sname.i, "-test-plot.pdf") 
      ggsave(file=filename, plot) 
    } 
} 

example(df1) 

Các lỗi tôi nhận được là: "Lỗi trong eval (expr, envir, enclos): đối tượng 'df2' không tìm thấy"

Tôi không hoàn toàn chắc chắn vấn đề là gì vì tôi đã tạo ra các vòng tương tự đã hoạt động trong quá khứ. Nếu tôi gán một giá trị cho i và bước qua mã trong vòng lặp nó hoạt động tốt. Tôi đang nghĩ một vấn đề môi trường? Hay là ggsave đang làm gì đó lung linh? Bất kỳ trợ giúp/con trỏ biết ơn nhận được. Cảm ơn.

+0

Khi tôi chạy mã của bạn, vấn đề là 'sname'. Nếu không có biến này được định nghĩa, 'i' cũng vẫn chưa được xác định, và điều tương tự xảy ra với' df2'. – vaettchen

+0

@vaettchen. Bạn đã chạy toàn bộ chức năng hay chỉ là vòng lặp?Tôi đã chạy lại chức năng ví dụ trên máy tính ở nhà của mình và vẫn gặp lỗi như đã nêu ở trên. Nó không cho tôi trên df2. – Bart

+0

đã chỉnh sửa tiêu đề câu hỏi để chỉ định vấn đề chính xác. –

Trả lời

4

Vấn đề của bạn không phải là quá nhiều mã của bạn, nhưng việc triển khai gói ggplot2. Gói này sử dụng đánh giá không chuẩn, và điều đó có thể làm hỏng kết quả của bạn.

Hãy xem mã ví dụ ở cuối bài đăng này. Tôi tạo ra trong môi trường toàn cầu một khung dữ liệu được gọi là df2 với các giá trị khác nhau. Nếu tôi chạy mã của bạn bây giờ, bạn sẽ có được âm mưu đó trông như thế này:

enter image description here

Lưu ý rằng trên trục X, nó sử dụng các ngày chính xác, nhưng các giá trị trên trục Y là những người từ dataframe df2 trong môi trường toàn cầu! Vì vậy, hàm aes() tìm kiếm dữ liệu ở hai vị trí khác nhau. Nếu bạn chỉ định tên của một biến làm ký hiệu (date), hàm đầu tiên sẽ nhìn vào khung dữ liệu được chỉ định trong cuộc gọi hàm. Tuy nhiên, không thể tìm thấy cụm từ như df2[,2] trong khung dữ liệu vì không có biến nào với tên đó. Do cách gói ggplot2 được xây dựng, R sẽ tìm kiếm trong môi trường toàn cục thay vì môi trường gọi.

Theo wici 's bình luận: Tùy chọn tốt nhất của bạn có lẽ là để sử dụng chức năng aes_string(), vì điều này cho phép bạn vượt qua aes ở dạng nhân vật, và chức năng này để đánh giá biểu thức trong môi trường chính xác:

plot <- ggplot()+ 
     geom_point(data=df2, aes_string(x="date", y=sname[i]))+ 
     geom_line(data=df2, aes_string(x="date", y=sname[i])) 

ngoài ra, bạn có thể khắc phục điều đó bằng cách sử dụng eval()parse() như thế này:

example <- function(df1){ 

    sname <- names(df1)[-1] 

    for (i in 1:length(sname)){ 
    df2 <- df1[,c(1, 1+i)] 
    df2$label <- factor(rep("ts", by=length(df2[,1]))) 

    aesy <- sname[i] 
    command <- paste("plot <- ggplot()+ 
     geom_point(data=df2, aes(x=date, y=",aesy,"))+ 
     geom_line(data=df2, aes(x=date, y=",aesy,"))") 

    eval(parse(text=command))      
    sname.i<-sname[i] 
    print(plot) 
    } 

Nếu bạn cố gắng mà ra với ví dụ kịch bản dưới đây, bạn sẽ thấy rằng khoảng thời gian này xung quanh bạn nhận được các giá trị chính xác được hiển thị. Lưu ý rằng đây là giải pháp tối ưu, như hầu hết các giải pháp liên quan đến eval(). Tôi sẽ đi theo số aes_string() tại đây.


VÍ DỤ SCRIPT

df1 <- data.frame(date = seq(as.Date("2015-01-01"), as.Date("2015-01-10"), 
          by = "day"), 
        site1 = runif(10), 
        site2 = runif(10), 
        site3 = runif(10)) 

df2 <- data.frame(date = seq(as.Date("2014-10-01"), as.Date("2014-10-10"), 
          by = "day"), 
        site1 = runif(10,10,20), 
        site2 = runif(10,10,20), 
        site3 = runif(10,10,20)) 

example <- function(df1){ 

    sname <- names(df1)[-1] 

    for (i in 1:length(sname)){ 
    df2 <- df1[,c(1, 1+i)] 
    df2$label <- factor(rep("ts", by=length(df2[,1]))) 

    plot <- ggplot()+ 
     geom_point(data=df2, aes(x=date, y=df2[,2]))+ 
     geom_line(data=df2, aes(x=date, y=df2[,2])) 

    sname.i<-sname[i] 
    print(plot) 
    } 
} 

example(df1) 
+2

Bạn hoàn toàn đúng, nhưng ggplot2 cũng cung cấp chức năng đánh giá thường xuyên về tính thẩm mỹ. Chỉ cần sử dụng 'aes_string (x =" date ", y = aesy)' làm trình tạo thẩm mỹ của bạn. – wici

+0

@Joris. Cảm ơn vì điều đó. Trong nỗ lực của tôi để chuyển đổi những gì tôi đã sử dụng trong đồ họa cơ sở để ggplot tôi có thể nhìn thấy nơi tôi đã đi sai. – Bart

+0

@wici. Cảm ơn vì tiền hỗ trợ. – Bart

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