r - 如何在 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
解决方案
这是一个具有挑战性的问题。我找到了一个解决方案,它使用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")
推荐阅读
- ios - image upload using POST-API when iOS app is in background
- forms - 如何在 SuiteCRM 中制作注册表单以在 CRM 上存储用户密码
- python - 如何在 python 数据框中将格式为 43004 的字符串转换为日期?
- react-native - 在 ReactNative 中以 Table 格式显示对象数组的值
- python - 如何不接受一个电子邮件地址用于 django 中的多个注册帐户?
- r - 根据另一个不同长度的数据帧中是否存在 NA 过滤一个数据帧
- android - java.lang.IllegalArgumentException:未知 URI:content://downloads/public_downloads/967
- postgresql - 如何将 NULL 值插入 PostgreSQL 表
- arrays - JSON数据并放入数组
- prestashop-1.7 - 将 prestashop 从 localhost 移动到服务器的问题