【问题标题】:how to make a loop column in R?如何在 R 中制作循环列?
【发布时间】:2020-03-07 01:16:32
【问题描述】:

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

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


    【解决方案1】:

    这是一个具有挑战性的问题。我找到了一个解决方案,它使用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 中的每个person 创建一个运行计数,每当该人离开其家庭区域时:

    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
    

    这与预期结果非常接近,但旅行目的地位于家乡区域的情况除外。因此,我们需要对这种情况进行更正。更正基于观察到 home zone 循环start_zoneend_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")
    

    【讨论】:

    • 已经准备好解决方案,但这让我感到羞耻。我需要深入研究一下data.table,它看起来很强大
    • @Mr.Rlover 谢谢。我在这里使用了data.table,因为它是rowid() 函数,而且我对data.table 的了解比dplyr 更熟悉。不过,我相信这种方法也可以在dplyr 中实现。
    • @Uwe 我注意到我的数据集更复杂。你能告诉我,如果我还有一个叫做旅行目的的专栏怎么样。现在,当zone=start_zone, until zone=end_zone` & purpose=home? 时开始循环
    • @elham,请发布一个包含预期结果的适当示例数据集的新问题。否则,我无法验证我的建议是否正确。谢谢。
    • @Uwe 你能看看这个帖子吗?stackoverflow.com/questions/60330449/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-01
    • 2022-11-07
    相关资源
    最近更新 更多