2016-11-19 3 views
-1

Я хотел бы построить в Rcpp такое подмножество iris набора данных:Rcpp Подменят ряды DataFrame

head(subset(iris, Species == "versicolor")) 

    Sepal.Length Sepal.Width Petal.Length Petal.Width Species 
51   7.0   3.2   4.7   1.4 versicolor 
52   6.4   3.2   4.5   1.5 versicolor 
53   6.9   3.1   4.9   1.5 versicolor 
54   5.5   2.3   4.0   1.3 versicolor 
55   6.5   2.8   4.6   1.5 versicolor 
56   5.7   2.8   4.5   1.3 versicolor 

Я знаю, как подмножество столбцов Rcpp::DataFrame - есть перегруженный оператор [, который работает как в R: x["var"]. Однако я не могу найти способ, который позволил бы мне подмножать строки DataFrame с нефиксированным числом столбцов.

Я хотел был бы написать функцию subset_rows_rcpp_iris которая принимает Rcpp::DataFrame (которая всегда будет диафрагмой) и CharacterVector level_of_species как входные сигналы. Он вернет объект DataFrame.

DataFrame subset_rows_rcpp_iris(DataFrame x, CharacterVector level_of_species) { 
    ... 
} 

Прежде всего, я хочу найти индексы строк, которые удовлетворяют логическому запросу. Моя проблема заключается в том, что если я получаю доступ к вектору Species в функции test, сохраните его как CharacterVector, а затем сравните его с level_of_species. Я получаю всегда только одно значение TRUE в случае setosa и значений FALSE в других случаях.

cppFunction(' 
    LogicalVector test(DataFrame x, CharacterVector level_of_species) { 
      CharacterVector sub = x["Species"]; 
      LogicalVector ind = sub == level_of_species; 
      return(ind); 
      } 
') 
head(test(iris, "setosa")) 

[1] TRUE FALSE FALSE FALSE FALSE FALSE 

Если это работало, я мог бы переписать test функции и использовать вектор с true/false значений подмножества каждого из столбца фрейма данных по отдельности, а затем объединить их снова с Rcpp::DataFrame::create.

+0

Да, действительно. Тем не менее, я не знаю, как я могу представить скалярный символ в C++. В Rcpp нет такого класса, как 'CharacterScalar'. 'String' тоже не работает. –

+1

правый правый !! моя ошибка. Поскольку там был NumericScalar, я подумал, что здесь тоже. Я думаю, что мы принимаем recylcing R в C++ здесь, когда делаем sub == level_of_species –

+0

, нам нужно иметь цикл for –

ответ

1
cppFunction('LogicalVector test(DataFrame x, StringVector level_of_species) { 
    using namespace std; 
    StringVector sub = x["Species"]; 
    std::string level = Rcpp::as<std::string>(level_of_species[0]); 
    Rcpp::LogicalVector ind(sub.size()); 
    for (int i = 0; i < sub.size(); i++){ 
     ind[i] = (sub[i] == level); 
    } 

    return(ind); 
}') 

xx=test(iris, "setosa") 
> table(xx) 
xx 
FALSE TRUE 
    100 50 

Подменю сделано !!! (я сам многому научился от этого вопроса..thanks!)

cppFunction('Rcpp::DataFrame test(DataFrame x, StringVector level_of_species) { 
    using namespace std; 
    StringVector sub = x["Species"]; 
    std::string level = Rcpp::as<std::string>(level_of_species[0]); 
    Rcpp::LogicalVector ind(sub.size()); 
    for (int i = 0; i < sub.size(); i++){ 
    ind[i] = (sub[i] == level); 
    } 

// extracting each column into a vector 
Rcpp::NumericVector SepalLength = x["Sepal.Length"]; 
Rcpp::NumericVector SepalWidth = x["Sepal.Width"]; 
Rcpp::NumericVector PetalLength = x["Petal.Length"]; 
Rcpp::NumericVector PetalWidth = x["Petal.Width"]; 


return Rcpp::DataFrame::create(Rcpp::Named("Sepal.Length") = SepalLength[ind], 
           Rcpp::Named("Sepal.Width") = SepalWidth[ind], 
           Rcpp::Named("Petal.Length") = PetalLength[ind], 
           Rcpp::Named("Petal.Width") = PetalWidth[ind] 
);}') 

yy=test(iris, "setosa") 
> str(yy) 
'data.frame': 50 obs. of 4 variables: 
$ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ... 
$ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ... 
$ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ... 
$ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ... 
Смежные вопросы