как сделать al oop столбец в R? - PullRequest
1 голос
/ 06 марта 2020

Я хочу сделать новый столбец l oop, как показано ниже:

Household   person    trip    ZoneOfHome    start_zone   end_zone
   1           1        1      22              22           13
   1           1        2      22              13           22
   1           1        3      22              22           34
   1           1        4      22              34           22 
   1           2        1      22              22           13
   1           2        2      22              13           22
   2           1        1      15              15           15
   2           1        2      15              15           15
   2           1        3      15              15           45
   2           1        4      15              45           15
   3           1        1      17              6            17
   3           1        2      17              17           10
   3           1        3      17              10           17              

Первый столбец - это индекс домохозяйства. второй столбец - это индекс лица в этом домохозяйстве. третий столбец - это показатель поездки каждого дня в каждой семье в течение дня. zoneOfHome - это зона дома этого домашнего хозяйства. start_zone - это зона, откуда человек начинает свое путешествие оттуда, а end_zone - это зона места, куда человек отправляется туда. L oop - это последовательность поездок, которая начинается дома и заканчивается дома. Мне нужен новый столбец 'l oop', который определяет l oop каждой поездки члена домохозяйства. Есть 3 разные ситуации, которые я показываю им в 3 разных домохозяйствах.

1 - В приведенном выше примере зона дома первой семьи - 22. Первая поездка первого человека из дома в зону 13. затем с 13 до дома. поэтому первый l oop этого человека:

22 -> 13 -> 22

второй l oop этого человека 22->34 -> 22

l oop второго человека 22 -> 13 -> 22

2 - второе домохозяйство немного сложнее. зона дома - 15. Поездка первого лица - от 15 до 15. (так что место близко к дому). это не означает, что 15-> 15 - это всего лишь oop. человек идет с 15 до 15 и обратно с 15 до 15, поэтому l oop равно

15 -> 15 -> 15 >- 15

, а его второе значение l oop равно 15 -> 45 -> 15.

3 - в третьем домохозяйстве первая поездка первого лица не из дома. Таким образом, мы удаляем первую поездку и начинаем с поездки, которая базируется дома. l oop составляет 17 -> 10 -> 17

Household   person    trip    ZoneOfHome    start_zone   end_zone       loop
   1           1        1      22              22           13            1
   1           1        2      22              13           22            1
   1           1        3      22              22           34            2
   1           1        4      22              34           22            2
   1           2        1      22              22           13            1
   1           2        2      22              13           22            1
   2           1        1      15              15           15            1
   2           1        2      15              15           15            1
   2           1        3      15              15           45            2
   2           1        4      15              45           15            2
   3           1        1      17              6            17            -
   3           1        2      17              17           10            1
   3           1        3      17              10           17            1

1 Ответ

2 голосов
/ 06 марта 2020

Это сложный вопрос. Я нашел решение, которое использует cumsum() и rowid(), чтобы вернуть ожидаемый результат для данного образца набора данных.

library(data.table)
setDT(DT)[, loop := cumsum((ZoneOfHome == start_zone) - rowid(start_zone, end_zone) + 1L), 
          by = .(Household, person)][]
    Household person trip ZoneOfHome start_zone end_zone loop
 1:         1      1    1         22         22       13    1
 2:         1      1    2         22         13       22    1
 3:         1      1    3         22         22       34    2
 4:         1      1    4         22         34       22    2
 5:         1      2    1         22         22       13    1
 6:         1      2    2         22         13       22    1
 7:         2      1    1         15         15       15    1
 8:         2      1    2         15         15       15    1
 9:         2      1    3         15         15       45    2
10:         2      1    4         15         45       15    2
11:         3      1    1         17          6       17    0
12:         3      1    2         17         17       10    1
13:         3      1    3         17         10       17    1

Объяснение

Сначала мы создаем текущий счетчик для каждого person в household всякий раз, когда человек покидает свою домашнюю зону :

DT[, loop1 := cumsum(ZoneOfHome == start_zone), by = .(Household, person)][]
    Household person trip ZoneOfHome start_zone end_zone loop1
 1:         1      1    1         22         22       13     1
 2:         1      1    2         22         13       22     1
 3:         1      1    3         22         22       34     2
 4:         1      1    4         22         34       22     2
 5:         1      2    1         22         22       13     1
 6:         1      2    2         22         13       22     1
 7:         2      1    1         15         15       15     1
 8:         2      1    2         15         15       15     2
 9:         2      1    3         15         15       45     3
10:         2      1    4         15         45       15     3
11:         3      1    1         17          6       17     0
12:         3      1    2         17         17       10     1
13:         3      1    3         17         10       17     1

Это очень близко к ожидаемому результату, за исключением случая, когда пункт назначения поездки находится в домашней зоне. Итак, нам нужна коррекция для этого случая. Поправка основана на наблюдении, что start_zone и end_zone домашней зоны l oop идентичны в последующих строках. Это можно посчитать с помощью функции rowid(), которая увеличивает счетчик при изменении одного из параметров:

DT[, corr_local := cumsum(rowid(start_zone, end_zone) - 1L), by = .(Household, person)][]
    Household person trip ZoneOfHome start_zone end_zone loop1 corr_local
 1:         1      1    1         22         22       13     1          0
 2:         1      1    2         22         13       22     1          0
 3:         1      1    3         22         22       34     2          0
 4:         1      1    4         22         34       22     2          0
 5:         1      2    1         22         22       13     1          0
 6:         1      2    2         22         13       22     1          0
 7:         2      1    1         15         15       15     1          0
 8:         2      1    2         15         15       15     2          1
 9:         2      1    3         15         15       45     3          1
10:         2      1    4         15         45       15     3          1
11:         3      1    1         17          6       17     0          0
12:         3      1    2         17         17       10     1          0
13:         3      1    3         17         10       17     1          0

Наконец, оба вспомогательных столбца необходимо объединить

DT[, loop := loop1 - corr_local, by = .(Household, person)][]
    Household person trip ZoneOfHome start_zone end_zone loop1 corr_local loop
 1:         1      1    1         22         22       13     1          0    1
 2:         1      1    2         22         13       22     1          0    1
 3:         1      1    3         22         22       34     2          0    2
 4:         1      1    4         22         34       22     2          0    2
 5:         1      2    1         22         22       13     1          0    1
 6:         1      2    2         22         13       22     1          0    1
 7:         2      1    1         15         15       15     1          0    1
 8:         2      1    2         15         15       15     2          1    1
 9:         2      1    3         15         15       45     3          1    2
10:         2      1    4         15         45       15     3          1    2
11:         3      1    1         17          6       17     0          0    0
12:         3      1    2         17         17       10     1          0    1
13:         3      1    3         17         10       17     1          0    1

Данные

library(data.table)
DT <- fread(
"Household   person    trip    ZoneOfHome    start_zone   end_zone
   1           1        1      22              22           13
   1           1        2      22              13           22
   1           1        3      22              22           34
   1           1        4      22              34           22 
   1           2        1      22              22           13
   1           2        2      22              13           22
   2           1        1      15              15           15
   2           1        2      15              15           15
   2           1        3      15              15           45
   2           1        4      15              45           15
   3           1        1      17              6            17
   3           1        2      17              17           10
   3           1        3      17              10           17")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...