2011-12-25 35 views
7

Tôi muốn tạo khung dữ liệu trong hàm Rcpp, nhưng khi tôi nhận được nó, nó không thực sự trông giống như một khung dữ liệu. Tôi đã cố gắng đẩy vectơ vv nhưng nó dẫn đến điều tương tự. Xem xét:xây dựng Khung dữ liệu trong Rcpp

RcppExport SEXP makeDataFrame(SEXP in) { 
    Rcpp::DataFrame dfin(in); 
    Rcpp::DataFrame dfout; 
    for (int i=0;i<dfin.length();i++) { 
     dfout.push_back(dfin(i)); 
    } 

    return dfout; 
} 

trong R:

> .Call("makeDataFrame",mtcars,"myPkg") 
[[1]] 
[1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2 10.4 
[16] 10.4 14.7 32.4 30.4 33.9 21.5 15.5 15.2 13.3 19.2 27.3 26.0 30.4 15.8 19.7 
[31] 15.0 21.4 

[[2]] 
[1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4 

[[3]] 
[1] 160.0 160.0 108.0 258.0 360.0 225.0 360.0 146.7 140.8 167.6 167.6 275.8 
[13] 275.8 275.8 472.0 460.0 440.0 78.7 75.7 71.1 120.1 318.0 304.0 350.0 
[25] 400.0 79.0 120.3 95.1 351.0 145.0 301.0 121.0 

[[4]] 
[1] 110 110 93 110 175 105 245 62 95 123 123 180 180 180 205 215 230 66 52 
[20] 65 97 150 150 245 175 66 91 113 264 175 335 109 

[[5]] 
[1] 3.90 3.90 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 3.92 3.07 3.07 3.07 2.93 
[16] 3.00 3.23 4.08 4.93 4.22 3.70 2.76 3.15 3.73 3.08 4.08 4.43 3.77 4.22 3.62 
[31] 3.54 4.11 

[[6]] 
[1] 2.620 2.875 2.320 3.215 3.440 3.460 3.570 3.190 3.150 3.440 3.440 4.070 
[13] 3.730 3.780 5.250 5.424 5.345 2.200 1.615 1.835 2.465 3.520 3.435 3.840 
[25] 3.845 1.935 2.140 1.513 3.170 2.770 3.570 2.780 

[[7]] 
[1] 16.46 17.02 18.61 19.44 17.02 20.22 15.84 20.00 22.90 18.30 18.90 17.40 
[13] 17.60 18.00 17.98 17.82 17.42 19.47 18.52 19.90 20.01 16.87 17.30 15.41 
[25] 17.05 18.90 16.70 16.90 14.50 15.50 14.60 18.60 

[[8]] 
[1] 0 0 1 1 0 1 0 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 1 0 1 0 0 0 1 

[[9]] 
[1] 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 

[[10]] 
[1] 4 4 4 3 3 3 3 4 4 4 4 3 3 3 3 3 3 4 4 4 3 3 3 3 3 4 5 5 5 5 5 4 

[[11]] 
[1] 4 4 1 1 2 1 4 2 2 4 4 3 3 3 4 4 4 1 2 1 1 2 2 4 2 1 2 2 4 6 8 2 
+4

Tôi không biết gì về Rcpp, thực sự, nhưng sẽ nó giúp bạn biết rằng trong R chính nó, tất cả các khung dữ liệu thực sự là danh sách? – joran

Trả lời

6

Dường như Rcpp có thể trả về một tệp dữ liệu thích hợp, miễn là bạn cung cấp tên rõ ràng. Tôi không chắc chắn làm thế nào để thích ứng này để ví dụ của bạn với tên tùy ý

mkdf <- ' 
    Rcpp::DataFrame dfin(input); 
    Rcpp::DataFrame dfout; 
    for (int i=0;i<dfin.length();i++) { 
     dfout.push_back(dfin(i)); 
    } 

    return Rcpp::DataFrame::create(Named("x")= dfout(1), Named("y") = dfout(2)); 
' 
library(inline) 
test <- cxxfunction(signature(input="data.frame"), 
           mkdf, plugin="Rcpp") 

test(input=head(iris)) 
+0

Vì vậy, rõ ràng, chúng tôi không thể tạo một khung dữ liệu mà số cột được quyết định trong thời gian chạy? – highBandWidth

+6

nếu bằng 'we' bạn có nghĩa là bạn và tôi, thì có thể là chính xác;) – baptiste

+0

Tôi nhớ rằng bạn có thể xác định số lượng cột tại thời gian chạy và tạo DataFrame tương ứng, vì tôi cũng cần một lần. Bạn không thể sử dụng tạo tĩnh trong tình huống đó. –

0

Tôi đồng tình với Joran. Đầu ra của hàm C được gọi từ bên trong R là danh sách tất cả các đối số của nó, cả "in" và "out", vì vậy mỗi "cột" của khung dữ liệu có thể được biểu diễn trong cuộc gọi hàm C làm đối số. Khi kết quả của cuộc gọi hàm C là trong R, tất cả những gì còn lại cần làm là trích xuất các phần tử danh sách đó bằng cách sử dụng danh sách chỉ mục và cung cấp cho chúng các tên thích hợp.

+0

Huh? Chúng tôi đang nói về C + + và Rcpp ở đây, không phải đồng bằng C. –

12

ngắn gọn:

  • DataFrames có thực sự giống như danh sách với những hạn chế gia tăng của việc phải có độ dài thông thường, vì vậy chúng được xây dựng tốt nhất cột theo cột.

  • Cách tốt nhất thường là tìm các bài kiểm tra đơn vị của chúng tôi. Cô ấy inst/unitTests/runit.DataFrame.R nhóm lại các bài kiểm tra cho lớp DataFrame.

  • Bạn cũng tìm thấy hàm thành viên .push_back() trong Rcpp mà chúng tôi đã thêm để thuận tiện và tương tự với STL. Chúng tôi cảnh báo rằng nó không được khuyến cáo: do sự khác biệt với cách thức đối tượng R được xây dựng, chúng tôi về cơ bản luôn luôn cần phải làm bản sao đầy đủ .push_backkhông phải là rất hiệu quả.

  • Mặc dù tôi trả lời thường xuyên ở đây, các rcpp-devel liệt kê một nơi tốt hơn cho các câu hỏi Rcpp.

+1

như của bây giờ, tôi không có một cách tốt hơn để thêm một cái gì đó vào một khung dữ liệu hơn push_back. Tôi đưa vào giải pháp tôi có thể nghĩ ra.Có một hàm bên trong 'grow'. 1 cho chỉ ra nó mặc dù. – highBandWidth

+0

Tôi sẽ phát triển các cột trước tiên (đặt trước phân bổ posisbly) và sau đó lắp ráp chúng trong một data.frame. –

+0

như vậy là có một cách để lắp ráp các cột trong một khung dữ liệu khác với tĩnh 'tạo'? Tôi không tìm thấy bất cứ điều gì làm điều này trong các bài kiểm tra đơn vị. – highBandWidth

6

Sử dụng thông tin từ @ của answer Baptiste, đây là những gì cuối cùng không đưa ra một khung dữ liệu cũng được hình thành:

RcppExport SEXP makeDataFrame(SEXP in) { 
    Rcpp::DataFrame dfin(in); 
    Rcpp::DataFrame dfout; 
    Rcpp::CharacterVector namevec; 
    std::string namestem = "Column Heading "; 
    for (int i=0;i<2;i++) { 
     dfout.push_back(dfin(i)); 
     namevec.push_back(namestem+std::string(1,(char)(((int)'a') + i))); 
    } 
    dfout.attr("names") = namevec; 
    Rcpp::DataFrame x; 
    Rcpp::Language call("as.data.frame",dfout); 
    x = call.eval(); 
    return x; 
} 

tôi nghĩ rằng điểm vẫn còn rằng điều này có thể không hiệu quả do push_back (như suggested bởi @Dirk) và đánh giá cuộc gọi ngôn ngữ thứ hai. Tôi đã tra cứu các đơn vị rcpp, và chưa thể tìm ra cái gì tốt hơn. Có ai có ý kiến ​​gì không?

Cập nhật: (! Thanks)

Sử dụng @ gợi ý Dirk, đây có vẻ là một giải pháp hiệu quả đơn giản:

RcppExport SEXP makeDataFrame(SEXP in) { 
    Rcpp::DataFrame dfin(in); 
    Rcpp::List myList(dfin.length()); 
    Rcpp::CharacterVector namevec; 
    std::string namestem = "Column Heading "; 
    for (int i=0;i<dfin.length();i++) { 
     myList[i] = dfin(i); // adding vectors 
     namevec.push_back(namestem+std::string(1,(char)(((int)'a') + i))); // making up column names 
    } 
    myList.attr("names") = namevec; 
    Rcpp::DataFrame dfout(myList); 
    return dfout; 
} 
+0

Tôi có xu hướng làm 'as.data.frame' ở cấp R. –

+0

Tôi vẫn không hiểu chức năng của bạn là gì. Tại sao bạn có một data.frame trên đầu vào? Xử lý chuỗi của bạn là * cách * quá phức tạp (nhìn lại, tại các bài kiểm tra đơn vị hoặc các tài liệu cho các vectơ chuỗi trong Rcpp). –

+0

Chức năng không làm bất cứ điều gì hữu ích. Tôi chỉ muốn có thể tạo thành một khung dữ liệu. Tôi sẽ thực sự tạo khung từ các tính toán/dữ liệu của riêng tôi, nhưng tôi chỉ cần một mẫu để đặt trong các vectơ cột và tên cùng nhau trong một khung dữ liệu, nơi tạo thành các vectơ cột v.v ... được thực hiện bằng C++ vì những tính toán này đắt tiền chương trình của tôi. Các tiêu đề cột/xử lý chuỗi về cơ bản là rác mà tôi không quan tâm. – highBandWidth

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