2016-04-14 16 views
-1

Rcpp işlevimde bir sorunum var. Temel olarak bir veri karesi (boyut N*K) ve giriş olarak bir sayısal vektör (boyut H < N) var ve çıktı olarak tamsayı vektörünün aynı satır dizinine sahip bir veri çerçevesini (boyut H * M) döndürmek istiyorum.Rcpp'de bir data.frame 'i id' tarafından belirterek 'istek türü ile uyumlu değil'

VERİ ÇERÇEVE:

val1 val2 val3 val4 
1 0.2059 A 14 
2 0.5700 B 61 
3 0.5354 C 24 
4 0.8123 D 78 
5 0.7542 E 39 
6 0.6433 F 17 
7 0.2452 G 96 
8 0.2557 H 93 
9 0.7208 I 36 
10 0.2565 L 12 

TAMSAYILI VEKTÖR:

2 
4 
7 
10 

ÇIKIŞ:

2 0.5700 B 61 
4 0.8123 D 78 
7 0.2452 G 96 
10 0.2565 L 12 

İşte benim kod. Yardım için şimdiden teşekkür ederiz:

#include <RcppArmadillo.h> 
using namespace Rcpp; 
// [[Rcpp::export]] 
DataFrame matchRows(DataFrame &OriginalDF, NumericVector &ReducedVector) 
{ 
    int nr1 = OriginalDF.nrows(), nc1= OriginalDF.size(); 
    int nr2 = ReducedVector.size(); 

    if (nr1 < nr2) throw std::range_error("Size of data frame has to be higher  than the target random subset!"); 

    std::map<double, DataFrame> X; 
    for (int j = 0; j < nr2; j++) 
    { 
    NumericVector tmp1=wrap(OriginalDF[ReducedVector[j]]); 
    tmp1.attr("dim")=Dimension(int(tmp1.size())/nc1,nc1); 

    DataFrame NewDF(wrap(tmp1)); 
    NewDF.push_back(OriginalDF[ReducedVector[j]]); 
    NewDF.attr("names")=OriginalDF.attr("names"); 

    X[ReducedVector[j]] = NewDF; 
    } 
    return wrap(X); 
} 

Kodumun önceki sürümü ne yazık ki RStudio'nun çökmesine neden oldu. İdeal sıfıra veri çerçevesini başlatmak ve daha sonra push_back() kullanarak değerleri eklemek için bir yolu vardır:

// [[Rcpp::export]] 
DataFrame matchRows(DataFrame &OriginalDF, NumericVector &ReducedVector) 
{ 
    int nr1 = OriginalDF.nrows(), nc1 = OriginalDF.size(); 
    int nr2 = ReducedVector.size(); 

    if (nr1 < nr2) throw std::range_error("Size of data frame has to be higher than the target random subset!"); 

    DataFrame NewDF; 
    for (int j = 0; j < nr2; j++) 
    { 
    NewDF.push_back(OriginalDF[ReducedVector[j]]); 
    } 
    return NewDF; 
} 
+0

Tam hata iletisini sağlayın ve kodunuzun hangi satırının hatayı attığını belirtin. Daha sonra bazı hata ayıklama işlemleri yapın, yani tüm değişkenlerin (özellikle atadığınız veya dönüştürdüğünüz) sahip olmalarını beklediğiniz türde olup olmadığını kontrol edin. – Roland

+0

Rcpp komut dosyası hatasız çalışır. Ancak, r işlevini çağırdığımda bana ileti hatası verir: 'istek türüyle uyumlu değil'. –

+0

[http://stackoverflow.com/questions/24353078/rstudio-crashes-with-rcpp-with-reproducible-codes] örneğini izleyerek hata ayıklamayı denedim, ancak yine de RStudio'da aynı sorunu yaşıyorum. –

cevap

2

Tamam, peki gerçekten sadece Rcpp satır kimlikleri ile data.frame alt kümesidir Burada yapmaya çalıştığımız ne.

örn.

D[c(2,4,7,10),] 

İlk olarak, kodunuzda tanımladığınız:

std::map<double, DataFrame> X; 

bu tip bir nesne ile başa çıkmak için hiçbir wrap() dönüşüm yoktur. Ayrıca, bu durumda, işlev tarafından belirtilen dönüş türü nedeniyle otomatik olarak dönüştürüldüğünden sarma gerçekten kullanılmamalıdır.

Bir data.frame'i alt kümeye almak için, her zaman tam bir kopya gerektirdiğinden ve bu nedenle çok verimli olmadığından, .push_back() özelliğini kullanmayın.

Bunun yerine, şöyle idx değişken ve Rcpp vector subsetting kullanmak istiyorum:

#include <Rcpp.h> 

// Extract rows from data.frame object in Rcpp 
// [[Rcpp::export]] 
Rcpp::DataFrame matchRows(Rcpp::DataFrame D, Rcpp::IntegerVector idx) { 

    // First, break apart each vector 
    Rcpp::IntegerVector val1 = D["val1"]; 
    Rcpp::NumericVector val2 = D["val2"]; 
    Rcpp::CharacterVector val3 = D["val3"]; 
    Rcpp::NumericVector val4 = D["val4"]; 

    // We assume that the index passed in starts at 1. 
    // Hence, we need to adjust the idx to start at 0 with: 
    idx = idx - 1; 

    // Next up, create a new DataFrame Object with selected rows subset. 
    return Rcpp::DataFrame::create(Rcpp::Named("val1") = val1[idx], 
           Rcpp::Named("val2") = val2[idx], 
           Rcpp::Named("val3") = val3[idx], 
           Rcpp::Named("val3") = val4[idx] 
           ); 
} 

/*** R 
# Make some data 
set.seed(1337) 
D = data.frame(val1 = 1:10, 
       val2 = rnorm(10), 
       val3 = letters[1:10], 
       val4 = sample(1:100, 10), 
       stringsAsFactor=FALSE) 

# Create index that starts at 1 instead of 0. 
# This will be converted in the C++ function. 
idx = c(2,4,7,10) 

matchRows(D, idx) 

*/ 

şeytan ayrıntılarda biz R leri 1 öncesi vs 0'dan başlayıp C++ 'ın endeksleri için hesaba 1 ile endeksini azaltacak olan endeksi çağırıyor. Bu, C++ kodunda da ele alınabilir. Yine de, bunu bir egzersiz olarak bırakacağım.

+0

Çok teşekkürler, bu iyi. Sayısal bir matris için olduğu gibi, değişkenlerin isimlerini açıklamaktan başka bir yol olduğunu umuyorum. –

İlgili konular