Вставить больше строк на основе условий из других строк - PullRequest
0 голосов
/ 08 января 2020

У меня есть следующий набор данных:

data have;
input year  firm_id location_id action  action_amount   operate new_entry
;
cards;
2013    28013   6085    1   10000   0   0
2015    28013   6085    1   12000   0   0
2015    28013   29189   1   10000   0   0
2016    28013   34019   1   5000    1   1
2017    28013   34019   0   0   1   2
2011    120609  9003    1   7000    0   0
2012    120609  9003    0   0   1   1
2013    120609  9003    1   5000    1   2
2012    247908  23001   1   9000    0   0
2013    247908  23001   1   8000    0   0
2014    247908  23001   1   8500    1   1
2015    247908  23001   0   0   1   2
2003    356123  1001    0   0   0   0
2004    356123  1001    0   0   0   0
2009    356123  1001    1   9800    1   1
;
run;

Я хочу добавить дополнительные строки и две новые переменные с именами "pre_action" и "pre_action_amount", чтобы получить следующий набор данных:

    data want;
input year  firm_id location_id action  action_amount   operate new_entry   pre_action  pre_action_amount
;
cards;
2013    28013   6085    1   10000   0   0   .   .
2014    28013   6085    0   0   0   0   1   10000
2015    28013   6085    1   12000   0   0   .   .
2016    28013   6085    0   0   0   0   1   12000
2015    28013   29189   1   6500    0   0   .   .
2016    28013   29189   0   0   0   0   1   6500
2016    28013   34019   1   5000    1   1   0   0
2017    28013   34019   0   0   1   2   .   .
2011    120609  9003    1   7000    0   0   .   .
2012    120609  9003    0   0   1   1   1   7000
2013    120609  9003    1   5000    1   2   .   .
2012    247908  23001   1   9000    0   0   .   .
2013    247908  23001   1   8000    0   0   1   9000
2014    247908  23001   1   8500    1   1   1   8000
2015    247908  23001   0   0   1   2   .   .
2003    356123  1001    0   0   0   0   .   .
2004    356123  1001    0   0   0   0   0   0
2005    356123  1001    0   0   0   0   0   0
2009    356123  1001    1   9800    1   1   0   0
;
run;

Правила таковы:

1) Сначала рассмотрим только те строки, которые имеют оператор = 0.

  • Для каждой пары firm_id и location_id, если в следующем году нет строка с одинаковыми firm_id и location_id, затем создайте новую строку со следующим годом и той же парой firm_id и location_id. Все переменные action, action_amount, opera и new_entry установлены в 0, а pre_action и pre_action_amount установлены в значение action и action_amount в предыдущем году. Пример: в 2013 году для пары firm_id / location_id 28013/6085 мы работали = 0. Но в 2014 году нет никаких наблюдений для этой пары firm_id / location_id. Таким образом, мы устанавливаем action, action_amount, opera и new_entry равным 0 и pre_action = 1 и pre_action_amount = 10000, которые являются значениями для action и action_amount в 2013 году.
  • Для каждой пары firm_id и location_id, если в следующем year есть строка с одинаковыми firm_id и location_id, затем просто установите pre_action и pre_action_amount равными значению action и action_amount в предыдущем году. Пример: в 2011 году для firm_id / location_id 120609/9003 мы работали = 0. Но в следующем 2012 году есть строка с этой парой firm_id / location_id. Поэтому мы устанавливаем pre_action = 1 и pre_action_amount = 7000, которые являются значениями для action и action_amount в 2011 году. Другой пример - в 2003 году для firm_id / location_id 356123 / 1001.

2) Теперь рассмотрим строки с new_entry = 1, которые еще не имеют значений pre_action и pre_action_amount. Установите pre_action и pre_action_amount равными 0.

3) Все остальные значения pre_action и pre_action_amount пусты.

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

1 Ответ

0 голосов
/ 08 января 2020

Если ваша основная проблема заключается в том, как получить доступ к информации из следующей записи, чтобы определить, есть ли пробел в year (так как в SAS нет функции lead()), ниже приведен пример, демонстрирующий использование POINT= опция оператора SET для точного выполнения этого.

Пример основан на слегка измененной версии ваших данных, поскольку:

  • уменьшает количество наблюдений и переменные в наборе данных.
  • он использует только одну переменную для определения идентификатора наблюдения.

Пример кода:

/* Example that shows how to use the POINT= option of the SET statement
   to look ahead at the next observation and decide whether there is a gap in YEAR. */
data example;
    input year id action_amount;
    cards;
2013    28013    10000
2015    28013    12000 
2016    28013    5000  
2017    28013    0  
2003    356123   250   
2004    356123   320   
2009    356123   9800  
;
run;

* Observations should be sorted by ID and YEAR for the next data step;
proc sort data=example; by id year; run;

* Process
data example_filled;
    set example;
    by id year;

    * Create the variable that will be used in the POINT= option of the SET statement
    * to retrieve information from the next observation;
    _next_obs = _N_ + 1;

    * Compute variables storing values from the previous observation;
    retain pre_action_amount;
    pre_action_amount = lag(action_amount);
    if first.id then
        call missing(pre_action_amount);

    * Analyze possible YEAR gaps in a BY group and partly fill them;
    if last.id then do;
        *** No gaps to check => simply output the last observation of the BY group;
        output;
    end;
    else do;
        *** We should check for gaps in YEAR;
        * 1) Send the current observation to the output dataset;
        output;

        * 2) Check if there is a gap > 1 based on the YEAR value from the next observation,
        * and if so, fill in (just) ONE observation
        * Note the use of the POINT= option of the SET statement to access info from next obs;
        set example(keep=year rename=(year=next_year)) POINT=_next_obs;
        if next_year > year + 1 then do;
            * Compute pre action values as the action values of the obs just output above;
            * All the other variables still maintain their values and will be carried over
            * this newly created obs;
            pre_action_amount = action_amount;
            year = year + 1;
            * Output the filled observation;
            output;
        end;
    end;

    drop next_year;
run;

Ожидаемый выходной набор данных example_filled (новые заполненные наблюдения: Obs = 2 и Obs = 8):

                                        action_    pre_action_
                 Obs    year      id       amount       amount

                  1     2013     28013     10000            .
                  2     2014     28013     10000        10000
                  3     2015     28013     12000        10000
                  4     2016     28013      5000        12000
                  5     2017     28013         0         5000
                  6     2003    356123       250            .
                  7     2004    356123       320          250
                  8     2005    356123       320          320
                  9     2009    356123      9800          320

Может оказаться полезным использовать этот пример в качестве основы для реализации описанной вами логики c для вычисления pre_action и pre_action_amount.

Примечание. Ниже приведены другие способы доступа к информации из следующее наблюдение в шаге данных: https://blogs.sas.com/content/sgf/2015/06/19/can-you-lag-and-lead-at-the-same-time-if-using-the-sas-data-step-yes-you-can/

...