Skip to content

[Rcpp-devel] Selecting rows and columns of matrices

7 messages · Chris DuBois, Dirk Eddelbuettel, Jason Lessels

#
Hi all,

I've copied the following from a portion of the "Using matrices" section of
the Rcpp Quick Reference
guide<http://cran.r-project.org/web/packages/Rcpp/vignettes/Rcpp-quickref.pdf>.
 I get a compilation error that I'm having trouble decoding.  Commenting out
the third line allows it to compile, so it must be something I've done wrong
with the column selector, but I don't see it.

Thanks in advance,
Chris

PS. My g++ version is 4.5.2, in case that helps.

src <- '
NumericMatrix xx(4, 5);
std::fill(xx.begin(), xx.end(), 8);
NumericMatrix::Column zzcol = xx( _, 1);
return(wrap(1));
 '
fun <-  cxxfunction(signature(x="numeric"), body = src, plugin="Rcpp")

file3011595e.cpp:35:39: error: invalid conversion from ?SEXPREC*? to ?int?
file3011595e.cpp:35:39: error:   initializing argument 1 of
?Rcpp::Matrix<RTYPE>::Proxy Rcpp::Matrix<RTYPE>::operator()(int, int) [with
int RTYPE = 14, Rcpp::Matrix<RTYPE>::Proxy = double&]?
file3011595e.cpp:35:39: error: conversion from
?Rcpp::traits::storage_type<14>::type? to non-scalar type
?Rcpp::Matrix<14>::Column? requested
make: *** [file3011595e.o] Error 1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20110518/284ad17a/attachment.htm>
#
On 18 May 2011 at 08:42, Chris DuBois wrote:
| Hi all,
| 
| I've copied the following from a portion of the "Using matrices" section of the
| Rcpp Quick Reference guide. ?I get a compilation error that I'm having trouble
| decoding. ?Commenting out the third line allows it to compile, so it must be
| something I've done wrong with the column selector, but I don't see it. ?
| 
| Thanks in advance,
| Chris
| 
| PS. My?g++ version is 4.5.2, in case that helps.
| 
| src <- '
| NumericMatrix xx(4, 5);
| std::fill(xx.begin(), xx.end(), 8);
| NumericMatrix::Column zzcol = xx( _, 1);
| return(wrap(1));
| ?'
| fun <- ?cxxfunction(signature(x="numeric"), body = src, plugin="Rcpp")
| 
| file3011595e.cpp:35:39: error: invalid conversion from ?SEXPREC*? to
| ?int?
| file3011595e.cpp:35:39: error: ? initializing argument 1 of ?Rcpp::Matrix
| <RTYPE>::Proxy Rcpp::Matrix<RTYPE>::operator()(int, int) [with int RTYPE = 14,
| Rcpp::Matrix<RTYPE>::Proxy = double&]?
| file3011595e.cpp:35:39: error: conversion from ?Rcpp::traits::storage_type
| <14>::type? to non-scalar type ?Rcpp::Matrix<14>::Column? requested
| make: *** [file3011595e.o] Error 1

Works for me:

R> src <- '
+ NumericMatrix xx(4, 5);
+ std::fill(xx.begin(), xx.end(), 8);
+ NumericMatrix::Column zzcol = xx( _, 1);
+ return(wrap(1));
+ '
R> fun <- cxxfunction(signature(x="numeric"), body = src, plugin="Rcpp")
R> fun(4.44)
[1] 1
R> 

Are you by chance using an ancient Rcpp version?

Dirk
#
Ah!  I had all the latest versions on my office computer and forgot to
update my laptop as well (which had Rcpp from 0.8.6. from 9/2010 or so).

Thanks.
Chris
On Wed, May 18, 2011 at 9:07 AM, Dirk Eddelbuettel <edd at debian.org> wrote:

            
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20110518/949bdd67/attachment-0001.htm>
#
Hi,
I have a very limited understanding of the class definition, but i was wondering if I could make a request for a minor change in relation to the two classes Datetime and the extension DatetimeVector. I have been successfully using Datetime class, passing both the date string and the format string, as this is allowed with the following definition;

00047	 Datetime::Datetime(const std::string &s, const std::string &fmt) {
00048                 Rcpp::Function strptime("strptime");    // we cheat and call strptime() from R
00049                 Rcpp::Function asPOSIXct("as.POSIXct"); // and we need to convert to POSIXct
00050                 m_dt = Rcpp::as<double>(asPOSIXct(strptime(s, fmt)));
00051                 update_tm();
00052     }

however the DatetimeVector definition uses;

00027         DatetimeVector::DatetimeVector(SEXP vec) throw(std::range_error) : v()  {
00028                 int i;
00029                 if (!Rf_isNumeric(vec) || Rf_isMatrix(vec) || Rf_isLogical(vec))
00030                         throw std::range_error("DatetimeVector: invalid numeric vector in constructor");
00031                 int len = Rf_length(vec);
00032                 if (len == 0)
00033                         throw std::range_error("DatetimeVector: null vector in constructor");
00034                 v.resize(len);
00035                 for (i = 0; i < len; i++)
00036                         v[i] = Datetime( static_cast<double>(REAL(vec)[i]));
00037         }


where line 36 calls Datetime without the ability to provide the format. Would it be possible for this to be changed to allow the format of the Datetime string. Currently I have to either convert the date string in R, or use an additional loop to convert the format, which make this slower than using the standard methods in R.

Sorry in advance if my understanding is incorrect.
Thanks
Jason
#
Hi Jason,
On 19 May 2011 at 11:00, Jason Lessels wrote:
| Hi,
| I have a very limited understanding of the class definition, but i was wondering if I could make a request for a minor change in relation to the two classes Datetime and the extension DatetimeVector. I have been successfully using Datetime class, passing both the date string and the format string, as this is allowed with the following definition;
| 
| 00047	 Datetime::Datetime(const std::string &s, const std::string &fmt) {
| 00048                 Rcpp::Function strptime("strptime");    // we cheat and call strptime() from R
| 00049                 Rcpp::Function asPOSIXct("as.POSIXct"); // and we need to convert to POSIXct
| 00050                 m_dt = Rcpp::as<double>(asPOSIXct(strptime(s, fmt)));
| 00051                 update_tm();
| 00052     }
| 
| however the DatetimeVector definition uses;
| 
| 00027         DatetimeVector::DatetimeVector(SEXP vec) throw(std::range_error) : v()  {
| 00028                 int i;
| 00029                 if (!Rf_isNumeric(vec) || Rf_isMatrix(vec) || Rf_isLogical(vec))
| 00030                         throw std::range_error("DatetimeVector: invalid numeric vector in constructor");
| 00031                 int len = Rf_length(vec);
| 00032                 if (len == 0)
| 00033                         throw std::range_error("DatetimeVector: null vector in constructor");
| 00034                 v.resize(len);
| 00035                 for (i = 0; i < len; i++)
| 00036                         v[i] = Datetime( static_cast<double>(REAL(vec)[i]));
| 00037         }
| 
| 
| where line 36 calls Datetime without the ability to provide the format. Would it be possible for this to be changed to allow the format of the Datetime string. Currently I have to either convert the date string in R, or use an additional loop to convert the format, which make this slower than using the standard methods in R.
| 
| Sorry in advance if my understanding is incorrect.

I fear you may be confused.  To see what constructors are defined, see the
corresponding class declaration in its header. For Datetime we get

    [...]
	      
    class Datetime {
    public:	
		Datetime();
		Datetime(SEXP s); 
		Datetime(const double &dt);	// from double, just like POSIXct
		Datetime(const std::string &s, const std::string &fmt="%Y-%m-%d %H:%M:%OS");
		Datetime(const Datetime &copy);

    [...]

implying that we can construct 'empty', from SEXP, from double, from string +
string and lastly from an existing Datetime.

Also, your second code quote is 'an existance proof' of the asked-for
constructor:  Had it now existed, the second quote would not have compiled.

As for your performance issues:  can you send a small mock-up example we can
grind through benchmark() or other timing tools?

Dirk
#
Hi Dirk,
Thanks for your help. I am 99% confident that there is a better method to my example below, but this is the only way i was able to pass the format string to for the datetime object.

src<-'
StringVector stringVec(dates);
int n_stringVec=stringVec.size();
std::string fmt =Rcpp::as<std::string>( format );

DatetimeVector  dateAll(n_stringVec);

std::string input;

for(int i=0;i<n_stringVec;i++){
  input = stringVec[i];
  Datetime dateTemp(input,fmt);
  dateAll[i] = dateTemp;
}

return wrap(dateAll);
'
library(inline)
cpp_DatetimeVector<-cxxfunction(signature(dates="string",format="string"),src,plugin="Rcpp")

####Create a fictional dataset
foo<-seq(as.POSIXct("1960-01-01 00:00:00"),as.POSIXct("2010-01-01 00:00:00"),by='hour')

system.time(test<-cpp_DatetimeVector(foo,"%Y-%m-%d %H:%M:%OS"))
#    user  system elapsed 
# 98.607   0.904 101.061 
system.time(test2<-strptime(foo,"%Y-%m-%d %H:%M:%OS"))
#    user  system elapsed 
# 14.089   0.261  14.501
On 19/05/2011, at 3:04 PM, Dirk Eddelbuettel wrote:

            
#
On 19 May 2011 at 15:27, Jason Lessels wrote:
| Hi Dirk,
| Thanks for your help. I am 99% confident that there is a better method to my example below, but this is the only way i was able to pass the format string to for the datetime object.
| 
| src<-'
| StringVector stringVec(dates);
| int n_stringVec=stringVec.size();
| std::string fmt =Rcpp::as<std::string>( format );
| 
| DatetimeVector  dateAll(n_stringVec);
| 
| std::string input;
| 
| for(int i=0;i<n_stringVec;i++){
|   input = stringVec[i];
|   Datetime dateTemp(input,fmt);
|   dateAll[i] = dateTemp;
| }
| 
| return wrap(dateAll);
| '
| library(inline)
| cpp_DatetimeVector<-cxxfunction(signature(dates="string",format="string"),src,plugin="Rcpp")
| 
| ####Create a fictional dataset
| foo<-seq(as.POSIXct("1960-01-01 00:00:00"),as.POSIXct("2010-01-01 00:00:00"),by='hour')
| 
| system.time(test<-cpp_DatetimeVector(foo,"%Y-%m-%d %H:%M:%OS"))
| #    user  system elapsed 
| # 98.607   0.904 101.061 
| system.time(test2<-strptime(foo,"%Y-%m-%d %H:%M:%OS"))
| #    user  system elapsed 
| # 14.089   0.261  14.501 

I see. Yes, the 101.061 is unappealing.  But dealing with timezones etc is
also very frustrating.  What I would is 

     test2 <- strptime(foo,"%Y-%m-%d %H:%M:%OS")   ## you now have POSIXct

     cpp_DatetimeVector( as.numeric(test2) )	   ## pass POSIXct down as numeric

with a rewritten cpp_DatetimeVector which does just

   src<-'
       DatetimeVector datevec(numericdates);       ## numericdates is as.numeric(POSIXct)

       // do stuff then return .....
   '

which should be very quick to execute.

In the uses I had, time always was (fractional) seconds since the epoch so I
never wrote another constructor....

Hope this helps, Dirk