Skip to content

Commit 587b342

Browse files
waltersomeddelbuettel
authored andcommitted
Implement push_back and push_front for DataFrame.
This explicitly defines push_back and push_back methods for DataFrame which copies row.names and class attributes from the original object. This fixes #1094 where these operations converted the object to a list. Tests for this behavior are also implemented.
1 parent 85f6b27 commit 587b342

File tree

4 files changed

+99
-0
lines changed

4 files changed

+99
-0
lines changed

ChangeLog

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717
* inst/NEWS.Rd: Idem
1818
* vignettes/rmd/Rcpp.bib: Idem
1919
* inst/bib/Rcpp.bib: Idem
20+
2020-07-01 Walter Somerville <[email protected]>
21+
22+
* inst/include/Rcpp/DataFrame.h: Implement explict push_back and
23+
push_front for DataFrame, which takes care to set the class and
24+
row.names attributes.
25+
* inst/tinyTest/test_dataframe.R Add in tests for push_back/push_front
26+
* inst/tinyTest/cpp/DataFrame.cpp
2027

2128
2020-06-27 Dirk Eddelbuettel <[email protected]>
2229

inst/include/Rcpp/DataFrame.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,42 @@ namespace Rcpp{
8383
return LENGTH(rn);
8484
}
8585

86+
template <typename T>
87+
void push_back( const T& object){
88+
R_xlen_t NewSize = std::max(object.size(), static_cast<R_xlen_t>(nrow()));
89+
Parent::push_back(object);
90+
IntegerVector RowNames = Range(1, NewSize);
91+
Rf_setAttrib(Parent::get__(), R_RowNamesSymbol, RowNames);
92+
Rf_setAttrib(Parent::get__(), R_ClassSymbol, Rf_mkString("data.frame"));
93+
}
94+
95+
template <typename T>
96+
void push_back( const T& object, const std::string& name ){
97+
R_xlen_t NewSize = std::max(object.size(), static_cast<R_xlen_t>(nrow()));
98+
Parent::push_back(object, name);
99+
IntegerVector RowNames = Range(1, NewSize);
100+
Rf_setAttrib(Parent::get__(), R_RowNamesSymbol, RowNames);
101+
Rf_setAttrib(Parent::get__(), R_ClassSymbol, Rf_mkString("data.frame"));
102+
}
103+
104+
template <typename T>
105+
void push_front( const T& object){
106+
R_xlen_t NewSize = std::max(object.size(), static_cast<R_xlen_t>(nrow()));
107+
Parent::push_front(object);
108+
IntegerVector RowNames = Range(1, NewSize);
109+
Rf_setAttrib(Parent::get__(), R_RowNamesSymbol, RowNames);
110+
Rf_setAttrib(Parent::get__(), R_ClassSymbol, Rf_mkString("data.frame"));
111+
}
112+
113+
template <typename T>
114+
void push_front( const T& object, const std::string& name){
115+
R_xlen_t NewSize = std::max(object.size(), static_cast<R_xlen_t>(nrow()));
116+
Parent::push_front(object, name);
117+
IntegerVector RowNames = Range(1, NewSize);
118+
Rf_setAttrib(Parent::get__(), R_RowNamesSymbol, RowNames);
119+
Rf_setAttrib(Parent::get__(), R_ClassSymbol, Rf_mkString("data.frame"));
120+
}
121+
86122
// Offer multiple variants to accomodate both old interface here and signatures in other classes
87123
inline int nrows() const { return DataFrame_Impl::nrow(); }
88124
inline int rows() const { return DataFrame_Impl::nrow(); }

inst/tinytest/cpp/DataFrame.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,39 @@ IntegerVector DataFrame_nrow( DataFrame df){
9494
IntegerVector DataFrame_ncol( DataFrame df){
9595
return IntegerVector::create(df.ncol(), df.cols());
9696
}
97+
98+
// [[Rcpp::export]]
99+
DataFrame DataFrame_PushBackNamed(){
100+
NumericVector u(2);
101+
NumericVector v(2);
102+
DataFrame df = DataFrame::create(_["u"] = u);
103+
df.push_back(v, "v");
104+
return df;
105+
}
106+
107+
// [[Rcpp::export]]
108+
DataFrame DataFrame_PushBackUnnamed(){
109+
NumericVector u(2);
110+
NumericVector v(2);
111+
DataFrame df = DataFrame::create(_["u"] = u);
112+
df.push_back(v);
113+
return df;
114+
}
115+
116+
// [[Rcpp::export]]
117+
DataFrame DataFrame_PushFrontNamed(){
118+
NumericVector u(2);
119+
NumericVector v(2);
120+
DataFrame df = DataFrame::create(_["u"] = u);
121+
df.push_front(v, "v");
122+
return df;
123+
}
124+
125+
// [[Rcpp::export]]
126+
DataFrame DataFrame_PushFrontUnnamed(){
127+
NumericVector u(2);
128+
NumericVector v(2);
129+
DataFrame df = DataFrame::create(_["u"] = u);
130+
df.push_front(v);
131+
return df;
132+
}

inst/tinytest/test_dataframe.R

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,23 @@ expect_equal( DataFrame_nrow( df ), rep(nrow(df), 2) )
7070
# test.DataFrame.ncol <- function(){
7171
df <- data.frame( x = 1:10, y = 1:10 )
7272
expect_equal( DataFrame_ncol( df ), rep(ncol(df), 2) )
73+
74+
# test.DataFrame.PushBackNamed <- function(){
75+
df <- data.frame( u = c(0, 0), v = c(0, 0) )
76+
expect_true( is.data.frame( DataFrame_PushBackNamed() ) )
77+
expect_equal( DataFrame_PushBackNamed(), df )
78+
79+
# test.DataFrame.PushBackUnamed <- function(){
80+
df <- data.frame( u = c(0, 0), c(0, 0), fix.empty.names = FALSE )
81+
expect_true( is.data.frame( DataFrame_PushBackUnnamed() ) )
82+
expect_equal( DataFrame_PushBackUnnamed(), df )
83+
84+
# test.DataFrame.PushFrontNamed <- function(){
85+
df <- data.frame( v = c(0, 0), u = c(0, 0) )
86+
expect_true( is.data.frame( DataFrame_PushFrontNamed() ) )
87+
expect_equal( DataFrame_PushFrontNamed(), df )
88+
89+
# test.DataFrame.PushFrontUnnamed <- function(){
90+
df <- data.frame( c(0, 0), u = c(0, 0), fix.empty.names = FALSE )
91+
expect_true( is.data.frame( DataFrame_PushFrontUnnamed() ) )
92+
expect_equal( DataFrame_PushFrontUnnamed(), df )

0 commit comments

Comments
 (0)