Заполните пропущенные значения в data.table с использованием скорости роста по категориям

голоса
3

У меня есть неполные серии (время), где я хотел бы, чтобы заполнить недостающие значения, используя доступные последние значения и темпы роста из другой серии, категории (страна). Категории, пропущенные значения не равна длина. Это требует применения функции от переменных последовательно: сначала я должен взять последнюю доступную точку данных (который может быть где угодно) и разделить его на 1 + темпе роста, а затем перейти к следующей точке данных и сделать то же самое.

Пример набора данных и желаемый результат:

require(data.table)
DT_desired<-data.table(category=c(rep(A,4),rep(B,4)),
           year=2010:2013,
           grwth=c(NA,.05,0.1,0,NA,0.1,0.15,0.2))
DT_desired[,values:=c(cumprod(c(1,DT_desired[category==A&!is.na(grwth),grwth]+1)),cumprod(c(1,DT_desired[category==B&!is.na(grwth),grwth]+1)))]

DT_example <- copy(DT_desired)[c(1,2,3,5),values:=NA]

То, что я пробовал: вы можете сделать это для цикла, но это неэффективно и не рекомендуется в R. Я полюбила эффективность data.table, и я бы желательно сделать это таким образом. Я попытался функция сдвига таблицы данных, которая только заполняет один отсутствующее значение (что логично, поскольку он пытается выполнить в то же время я думаю, когда все остальное отсутствует предыдущее значение).

DT_example[,values:=ifelse(is.na(values),shift(values,type = lead)/(1+shift(grwth,type = lead)),values),by=category]

Я собираю от других сообщений, которые вы, вероятно, можете сделать это с rollapply функцией пакета зоопарка, но я только что получил такое ощущение, что я должен быть в состоянии сделать это в таблице данных без еще одного дополнительного пакета, и что решение является относительно простого и элегантный, просто я не достаточно опытен, чтобы найти его.

Это очень хорошо может быть дубликат и извините, если я не заметил соответствующую должность, но ни один из того, что я нашел, сделал именно то, что я хочу.

Задан 27/11/2018 в 15:08
источник пользователем
На других языках...                            


1 ответов

голоса
1

Не уверен , если это было решено за пределами SO, но он поймал мой взгляд другого дня. Я не писал Rcpp в течение долгого времени , и полагал , что это будет хорошей практикой. Я знаю , что вы искали нативное data.tableрешение, так что не стесняйтесь взять его или оставить его:

Содержание foo.cppфайла:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector fillValues(NumericVector vals, NumericVector gRates){

  int n = vals.size();
  NumericVector out(n);

  double currentValue   = vals[n - 1];
  double currentGrowth  = gRates[n - 1];

  // initial assignment
  out[n - 1] = currentValue;

  for(int i = n - 2; i >= 0; i--){

    if(NumericVector::is_na(vals[i])){
      // If val[i] is na, we need prior values to populate it
      if(!((currentValue || currentValue == 0) && (currentGrowth || currentGrowth == 0))){
        // We need a currentValue and currentGrowth to base growth rate on, throw error
        Rcpp::stop("NaN Values for rates or value when needed actual value");
      } else {
        // Update value
        out[i] = currentValue / (1 + currentGrowth);
      }
    } else {
      out[i] = vals[i];
    }

    // update
    currentValue = out[i];
    if(!NumericVector::is_na(gRates[i])){
      currentGrowth = gRates[i];
    }
  }

  return out;
}

/*** R
require(data.table)
DT_desired<-data.table(category=c(rep("A",4),rep("B",4)),
                       year=2010:2013,
                       grwth=c(NA,.05,0.1,0,NA,0.1,0.15,0.2))

DT_desired[,values:=c(cumprod(c(1,DT_desired[category=="A"&!is.na(grwth),grwth]+1)),cumprod(c(1,DT_desired[category=="B"&!is.na(grwth),grwth]+1)))]

DT_example <- copy(DT_desired)[c(1,2,3,5),values:=NA]

DT_desired[]
DT_example[]

DT_example[, values:= fillValues(values, grwth)][]
*/

Затем запустите его:

> Rcpp::sourceCpp('foo.cpp')

# Removed output that created example data

> DT_desired[]
   category year grwth values
1:        A 2010    NA  1.000
2:        A 2011  0.05  1.050
3:        A 2012  0.10  1.155
4:        A 2013  0.00  1.155
5:        B 2010    NA  1.000
6:        B 2011  0.10  1.100
7:        B 2012  0.15  1.265
8:        B 2013  0.20  1.518

> DT_example[]
   category year grwth values
1:        A 2010    NA     NA
2:        A 2011  0.05     NA
3:        A 2012  0.10     NA
4:        A 2013  0.00  1.155
5:        B 2010    NA     NA
6:        B 2011  0.10  1.100
7:        B 2012  0.15  1.265
8:        B 2013  0.20  1.518

> DT_example[, values:= fillValues(values, grwth)][]
   category year grwth values
1:        A 2010    NA  1.000
2:        A 2011  0.05  1.050
3:        A 2012  0.10  1.155
4:        A 2013  0.00  1.155
5:        B 2010    NA  1.000
6:        B 2011  0.10  1.100
7:        B 2012  0.15  1.265
8:        B 2013  0.20  1.518

Обратите внимание, это бежит обратно на фронт, поэтому предполагается, что вы хотите, чтобы начать с самой последней записи и работы с записями из дальше назад. Он также предполагает набор данных отсортирован.

Ответил 29/11/2018 в 16:44
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more