基于此问题
我想使用Rcpp 将生成的字符列转换为日期。这是我的初始代码,它将因子级别转换为字符列。
样本数据:
df <- data.frame(
col1 = c(1, 2, 3),
col2 = c("a", "b", "c"),
col3 = factor(
x = c("01/01/2017 00:00:00", "01/06/2017 00:00:00", "05/01/2017 00:00:00"),
levels = c("01/01/2017 00:00:00", "01/06/2017 00:00:00", "05/01/2017 00:00:00")
),
col4 = factor(
x = c("01/01/2018 00:00:00", "01/06/2018 00:00:00", "05/01/2018 00:00:00"),
levels = c("01/01/2018 00:00:00", "01/06/2018 00:00:00", "05/01/2018 00:00:00")
),
stringsAsFactors = FALSE
)
Rcpp代码:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
void GetDateFromFactorLevels(DataFrame df1) {
CharacterVector varNames = df1.names();
for(int i = 0; i < df1.length(); i++) {
if(Rf_isFactor(df1[i]) == 1) {
IntegerVector tempVec=df1[i];
df1[i] = tempVec.attr("levels");
}
}
}
> GetDateFromFactorLevels(df)
> sapply(df, class)
col1 col2 col3 col4
"numeric" "character" "character" "character"
> df
col1 col2 col3 col4
1 1 a 01/01/2017 00:00:00 01/01/2018 00:00:00
2 2 b 01/06/2017 00:00:00 01/06/2018 00:00:00
3 3 c 05/01/2017 00:00:00 05/01/2018 00:00:00
是否可以这样做并得到类似的东西?
> sapply(df, class)
col1 col2 col3 col4
"numeric" "character" "Date" "Date"
> df
col1 col2 col3 col4
1 1 a 2017-01-01 2018-01-01
2 2 b 2017-06-01 2018-06-01
3 3 c 2017-01-05 2018-01-05
答案 0 :(得分:3)
是的。如Dirk Eddelbuettel's answer所述,如果您可以使用DatetimeVector并将其转换为DateVector,则将容易得多。如果您确实必须处理各种因素,那么作为一种快速而肮脏的解决方案(其他人可能会提供更优雅的解决方案),您可以这样做:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
void GetDateFromFactorLevels(DataFrame df1) {
int n = df1.nrows();
for ( int i = 0; i < df1.length(); i++ ) {
if ( Rf_isFactor(df1[i]) == 1 ) {
IntegerVector values = df1[i]; // Get the integer values
CharacterVector levels = values.attr("levels"); // and the levels
DateVector result(n); // Make an empty DateVector
for ( int j = 0; j < n; ++j ) {
// And for every element of the factor, look up the level
// value corresponding to its integer value,
// and construct a Date by turning it into an std::string
// (and specifying the applicable date format)
result[j] = Date(std::string(levels[values[j] - 1]), "%d/%m/%Y");
}
// Then just replace the df1 column with the DateVector
df1[i] = result;
}
}
}
从R调用时:
Rcpp::sourceCpp("date-stuff.cpp")
df <- data.frame(
col1 = c(1, 2, 3),
col2 = c("a", "b", "c"),
col3 = factor(
x = c("01/01/2017 00:00:00", "01/06/2017 00:00:00", "05/01/2017 00:00:00"),
levels = c("01/01/2017 00:00:00", "01/06/2017 00:00:00", "05/01/2017 00:00:00")
),
col4 = factor(
x = c("01/01/2018 00:00:00", "01/06/2018 00:00:00", "05/01/2018 00:00:00"),
levels = c("01/01/2018 00:00:00", "01/06/2018 00:00:00", "05/01/2018 00:00:00")
),
stringsAsFactors = FALSE
)
sapply(df, class)
#> col1 col2 col3 col4
#> "numeric" "character" "factor" "factor"
df
#> col1 col2 col3 col4
#> 1 1 a 01/01/2017 00:00:00 01/01/2018 00:00:00
#> 2 2 b 01/06/2017 00:00:00 01/06/2018 00:00:00
#> 3 3 c 05/01/2017 00:00:00 05/01/2018 00:00:00
GetDateFromFactorLevels(df)
sapply(df, class)
#> col1 col2 col3 col4
#> "numeric" "character" "Date" "Date"
df
#> col1 col2 col3 col4
#> 1 1 a 2017-01-01 2018-01-01
#> 2 2 b 2017-06-01 2018-06-01
#> 3 3 c 2017-01-05 2018-01-05
由reprex package(v0.2.1)于2018-10-11创建
答案 1 :(得分:1)
好的。看一下RcppExamples软件包和source repository,其中有
实际上,您可以通过使用向量成员函数attr()
更改class属性来实现。但是构造新向量的简单方法也应该起作用。