我正在使用一个旅行数据集,该数据集提供每个人旅行的不连续部分的信息,包括该部分的距离和目的(例如上班,购物,回家)。它被组织在一个数据框中。我想将这些段分组为我所说的“链接”或“循环”行程,每当前面的段中有回程时增加链/回路的数量。
在r中,我试图构造一个包含ifelse的for循环,该循环引用来自先前迭代的变量值,然后填充一个我已经用空值创建的新列。 (我知道这听起来有点钝)。基本上,我试图做出与在Excel中构造一系列嵌套if的Excel类似的工作。 (= IF(DF2 = DF1,IF(DG1 = 11,DI1 + 1,DI1),1)。这是第三行的公式,它引用的是紧接在前一行的值。
这是数据的dput代码输出:
structure(list(h_id = c(1000002L, 1000002L, 1000002L, 1000002L,
1000013L, 1000013L, 1000013L, 1000013L, 1000013L, 1000013L, 1000013L, 1000013L), p_ID = c(10000022L, 10000022L, 10000022L,
10000022L, 10000131L, 10000131L, 10000132L,10000132L, 10000132L,10000132L,10000132L,10000132L), t_pur = c(6L, 11L, 7L, 11L,
5L, 11L, 1L, 2L, 2L, 11L, 6L, 11L), t_distance = c(753.154936, 753.154936, 4681.630497,
4681.630497, 616.0517311, 616.0517311, 9626,7984, 641.3675, 15076.6182, 21407.5585, 24273.3116, 24273.3116), X = c(1L, 1L, 2L, 2L,
1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L), Conc = c("10000022-1", "10000022-1", "10000022-2", "10000022-2",
"10000131-1", "10000131-1", "10000132-1", "10000132-1", "10000132-1", "10000132-1", "10000132-2", "10000132-2" ), t_mode1 = c(1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L,
1L), has_work = c(0, 0, 0, 0, 0, 0,1, 0, 0, 0, 0, 0), newcol = c(1, 1, 1, 1, 1,
1, 1, 1, 1, 1,1, 1)), .Names = c("h_id", "p_ID", "t_pur", "t_distance", "X", "Conc",
"t_mode1", "has_work", "newcol"), row.names = 3:14, class = "data.frame")
for (i in 1:nrow(loops4)) {
ifelse(i == 1, loops4$newcol[i] <- 1,
ifelse(loops4$p_ID[i-1]==loops4$p_ID,
ifelse(loops4$t_pur[i-1]==11,
loops4$newcol[i] <- loops4$newcol[i-1]+1,
loops4$newcol[i-1]), loops4$newcol[i] <- 1))
}
在这里,loops4是我的数据帧。我创建了newcol来保存循环标识符。 p_ID是与每个人相关联的唯一标识符,t_pur是行程段的目的,“ 11”是与“回家”目的相对应的值。 (我想在前面的段每次返回时都启动一个新的循环标识符)。之后,我可以将唯一的人员ID和循环ID串联起来,为每个循环创建唯一的标识符。第一个ifelse只是为第一条记录分配一个1到循环标识符,因为该循环没有先前的值可以查询
我希望循环遍历数据帧的每一行,首先检查记录是否与上一条记录中提到的人相同。如果是这样,则应检查上一行的行程目的是否为“ 11”。如果是这样,则应在前面的标识符上加1以表示新的循环。如果它的跳闸目的不是“ 11”,则它应分配与上一行完全相同的循环标识符,然后移至下一行。它运行时,首先,似乎要花费大量时间,其次,它用1填充所有内容,而不是按照我的预期进行递增和重新启动。
我期望这样的数据框。 X是从Excel正确计算得出的值。 newcol是我试图在newcol中计算r中的值的列。 newcol值应与X相同,但不相同。 (我更新了下表以在newcol中反映我希望在输出中看到的内容)。
h_id p_ID t_pur t_distance X Conc t_mode1 has_work newcol
1000002 10000022 6 753.2 1 10000022-1 1 0 1
1000002 10000022 11 753.2 1 10000022-1 1 0 1
1000002 10000022 7 4681.6 2 10000022-2 1 0 2
1000002 10000022 11 4681.6 2 10000022-2 1 0 2
1000013 10000131 5 616.1 1 10000131-1 1 0 1
1000013 10000131 11 616.1 1 10000131-1 1 0 1
1000013 10000132 1 9626.8 1 10000132-1 1 1 1
1000013 10000132 2 641.4 1 10000132-1 1 0 1
1000013 10000132 2 15076.6 1 10000132-1 1 0 1
1000013 10000132 11 21407.6 1 10000132-1 1 0 1
1000013 10000132 6 24273.3 2 10000132-2 1 0 2
1000013 10000132 11 24273.3 2 10000132-2 1 0 2
更新:
我回过头来,根据下面的评论对ifelse构造中的赋值进行了一些思考,意识到这没有多大意义。所以我尝试重写代码,如下所示:
for (i in 1:nrow(loops4)) {
loops4$newcol[i] <- ifelse(i == 1, 1, ifelse (loops4$p_ID[i-1]==loops4$p_ID[i], ifelse(loops4$t_pur[i-1]==11, loops4$newcol[i-1]+1, loops$newcol[i-1], 1)))
}
但是我得到了同样的意外结果。
更新后的更新:
以前的Dput数据中可能存在错误。我手动添加了一些值。我在下面粘贴了新的dput数据。
structure(list(h_id = c(1000002L, 1000002L, 1000002L, 1000002L,
1000013L, 1000013L, 1000013L, 1000013L, 1000013L, 1000013L, 1000013L,
1000013L), p_ID = c(10000022L, 10000022L, 10000022L, 10000022L,
10000131L, 10000131L, 10000132L, 10000132L, 10000132L, 10000132L,
10000132L, 10000132L), t_pur = c(6L, 11L, 7L, 11L, 5L, 11L, 1L,
2L, 2L, 11L, 6L, 11L), t_distance = c(753.154936, 753.154936,
4681.630497, 4681.630497, 616.0517311, 616.0517311, 9626.798385,
641.3674532, 15076.61817, 21407.55851, 24273.31161, 24273.31161
), X = c(1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L), Conc = c("10000022-1",
"10000022-1", "10000022-2", "10000022-2", "10000131-1", "10000131-1",
"10000132-1", "10000132-1", "10000132-1", "10000132-1", "10000132-2",
"10000132-2"), t_mode1 = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L), has_work = c(0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0),
newcol = c(1L, 1L, 2L, 2L, 1L, 1L, 0L, 0L, 1L, 1L, 2L, 2L
)), .Names = c("h_id", "p_ID", "t_pur", "t_distance", "X",
"Conc", "t_mode1", "has_work", "newcol"), class = c("tbl_df",
"tbl", "data.frame"), row.names = c(NA, -12L))
并且我尝试了以下有用的dplyr方法。
loops_good <- loops5 %>%
group_by(h_id) %>% group_by (p_ID) %>%
mutate(newcol = cumsum(lead(t_pur, default = 0) == 11)) %>%
ungroup()
我得到的结果几乎是我一直期望的结果。但不完全是。第7行到第10行应在newcol中与相同的标识符一起分组,因为没有中间的“ 11”。 t_pur序列为1、2、2、11。但是在下面的输出中,newcol值分别为0、0、1、1。
基本上,我正在尝试将各个部分链接成整体行程,从每次有t_pur ==“ 11”表示的返程回家开始。有时,它只是一个往返(两个部分)。但有时,如第7-10行,它是4个细分。
实际输出:
h_id p_ID t_pur t_distance X Conc t_mode1 has_work newcol
<int> <int> <int> <dbl> <int> <chr> <int> <dbl> <int>
1 1000002 10000022 6 753. 1 10000022-1 1 0 1
2 1000002 10000022 11 753. 1 10000022-1 1 0 1
3 1000002 10000022 7 4682. 2 10000022-2 1 0 2
4 1000002 10000022 11 4682. 2 10000022-2 1 0 2
5 1000013 10000131 5 616. 1 10000131-1 1 0 1
6 1000013 10000131 11 616. 1 10000131-1 1 0 1
7 1000013 10000132 1 9627. 1 10000132-1 1 1 0
8 1000013 10000132 2 641. 1 10000132-1 1 0 0
9 1000013 10000132 2 15077. 1 10000132-1 1 0 1
10 1000013 10000132 11 21408. 1 10000132-1 1 0 1
11 1000013 10000132 6 24273. 2 10000132-2 1 0 2
12 1000013 10000132 11 24273. 2 10000132-2 1 0 2
希望输出:
h_id p_ID t_pur t_distance X Conc t_mode1 has_work newcol
<int> <int> <int> <dbl> <int> <chr> <int> <dbl> <int>
1 1000002 10000022 6 753. 1 10000022-1 1 0 1
2 1000002 10000022 11 753. 1 10000022-1 1 0 1
3 1000002 10000022 7 4682. 2 10000022-2 1 0 2
4 1000002 10000022 11 4682. 2 10000022-2 1 0 2
5 1000013 10000131 5 616. 1 10000131-1 1 0 1
6 1000013 10000131 11 616. 1 10000131-1 1 0 1
7 1000013 10000132 1 9627. 1 10000132-1 1 1 1
8 1000013 10000132 2 641. 1 10000132-1 1 0 1
9 1000013 10000132 2 15077. 1 10000132-1 1 0 1
10 1000013 10000132 11 21408. 1 10000132-1 1 0 1
11 1000013 10000132 6 24273. 2 10000132-2 1 0 2
12 1000013 10000132 11 24273. 2 10000132-2 1 0 2
答案 0 :(得分:0)
我想我知道你想要的是什么...
说明:
dplyr::group_by
,data.table
分组by=
和基数R的by()
lead
或shift
,我们包含 next 行的值的逻辑,以便将其分配给 this 行; b / c这两个函数都不知道在查看特定人的最后一行时该怎么做,我们必须使用default=
,fill=
提供默认值,或者使用{{1 }} 已编辑以获取最新的逻辑和理解。
c(...[-1], 0)
dplyr
library(dplyr)
x %>%
group_by(p_ID) %>%
mutate(newcol = cumsum(lag(t_pur == 11, default = TRUE))) %>%
ungroup()
# # A tibble: 12 x 9
# h_id p_ID t_pur t_distance X Conc t_mode1 has_work newcol
# <int> <int> <int> <dbl> <int> <chr> <int> <dbl> <int>
# 1 1000002 10000022 6 753. 1 10000022-1 1 0 1
# 2 1000002 10000022 11 753. 1 10000022-1 1 0 1
# 3 1000002 10000022 7 4682. 2 10000022-2 1 0 2
# 4 1000002 10000022 11 4682. 2 10000022-2 1 0 2
# 5 1000013 10000131 5 616. 1 10000131-1 1 0 1
# 6 1000013 10000131 11 616. 1 10000131-1 1 0 1
# 7 1000013 10000132 1 9627. 1 10000132-1 1 1 1
# 8 1000013 10000132 2 641. 1 10000132-1 1 0 1
# 9 1000013 10000132 2 15077. 1 10000132-1 1 0 1
# 10 1000013 10000132 11 21408. 1 10000132-1 1 0 1
# 11 1000013 10000132 6 24273. 2 10000132-2 1 0 2
# 12 1000013 10000132 11 24273. 2 10000132-2 1 0 2
data.table
library(data.table)
xDT <- x
xDT$newcol <- NULL
setDT(xDT)
xDT[, newcol := cumsum(shift(t_pur == 11, type = "lag", fill = TRUE)), by = "p_ID"]