首页 > 解决方案 > 如何在 R 中制作循环列?

问题描述

我想创建一个新的列循环,如下所示:

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 是一个人前往那里的地方的区域。循环是从家开始到家结束的一系列行程。我想要一个新列“循环”,它确定家庭成员每次旅行的循环。我在 3 个不同的家庭中展示了 3 种不同的情况。

1-在上面的例子中,第一个家庭的家庭区域是 22。第一个人的第一次旅行是从家到 13 区。然后从 13 到家。所以这个人的第一个循环是:

22 -> 13 -> 22

这个人的第二个循环是22->34 -> 22

第二人称的循环是22 -> 13 -> 22

2-第二个家庭有点复杂。家的区域是15。第一个人的旅行是15到15。(所以离家很近的地方)。这并不意味着 15-> 15 是一个循环。这个人从 15 到 15,然后从 15 到 15,所以循环是

15 -> 15 -> 15 >- 15

他的第二个循环是15 -> 45 -> 15

3- 在第三户中,第一人的第一次旅行不在家。因此,我们删除了第一次旅行并从以家为基础的旅行开始。循环是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

标签: r

解决方案


这是一个具有挑战性的问题。我找到了一个解决方案,它使用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。这可以在参数之一更改时增加计数器的功能的帮助下进行计数: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")

推荐阅读