Преобразуйте столбцы фактора в столбцы даты в R data.frame, используя Rcpp - PullRequest
0 голосов
/ 11 октября 2018

На основании этого вопроса

Как получить доступ к уровням факторов data.frame в Rcpp, когда он передается в качестве аргумента от R?

Я хочу преобразовать результирующие символьные столбцы в даты , используя 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

Ответы [ 2 ]

0 голосов
/ 11 октября 2018

Да.* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * [2]. Было бы намного проще, если бы вы могли работать с 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

Создано в 2018-10-11 пакетом Представление (v0.2.1)

0 голосов
/ 11 октября 2018

Конечно.Посмотрите на пакет RcppExamples и исходный репозиторий , который имеет

Фактически вы можете получить это, просто изменив атрибут класса с помощью функции-члена вектора attr().Но простой способ построения новых векторов тоже должен работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...