如何在 R 数据框中的新列中获取变量的唯一值?
How to get the unique values of a variable in new columns in a R Data frame?
示例数据
mydf <- data.frame(Vehicle.ID = c(1,1,1,1,1,1,1,1), Frame.ID = c(1,2,3,4,5,6,7,8),
Lane = c(1,1,2,2,2,3,3,3), lane.change = c(".", ".", "yes", ".", ".","yes",".","."),
Preceding.Vehicle.ID = c(10,10,5,5,5,6,6,6),
Following.Vehicle.ID = c(20,20,50,50,50,30,30,30))
数据说明
Vehicle.ID:车辆ID
Frame.ID:帧数(1帧=0.1秒)
Lane: 当前占用的车道数
lane.change:“。”表示车辆在此帧中未变道,"yes"表示车辆在此帧中变道
Preceding.Vehicle.ID and Following.Vehicle.ID:当前车道前车和后车ID,在给定的框架中。
我想做的事情:
我要查找:
1. 车辆占用的所有车道。当前车道在 "Lane" 列中给出。车辆移动到的所有其他车道是目标车道。我想创建包含所有目标车道的车道编号的新列,即 target.lane1、target.lane2 等.
2. 同样,我想将所有前车 ID 和后车 ID 放入新列中,即目标车道 1 和 2 中的前车:PVtl1、PVtl2,以及目标车道 1 和 2 中的后车:FVtl1、FVtl2。
最终需要的数据框形式:
mydf.final <- mydf %>%
mutate(target.lane1 = 2, PVtl1 = 5, FVtl1 = 50,
target.lane2 = 3, PVtl2 = 6, FVtl2 = 30)
我尝试过的:
老实说,我不知道该怎么做。我尝试使用:
> mydf <- mydf %>%
+ mutate(pvtl1 = data.frame(unique(Preceding.Vehicle.ID)))
Error: not compatible with STRSXP
但如您所见,出现错误。
请指导我。我想为此使用 dplyr
。
编辑:
我已经尝试使用 for loop
并且它适用于此示例数据:
for (i in 1:length(unique(mydf$Lane))){
mydf[,paste("target.lane",i, sep=".")] = unique(mydf$Lane)[i]
mydf[,paste("PVtl",i, sep=".")] = unique(mydf$Preceding.Vehicle.ID)[i]
mydf[,paste("FVtl",i, sep=".")] = unique(mydf$Following.Vehicle.ID)[i]
}
在这里,target.lane.1、PVtl1 和 FVtl1 没有用,因为它们只包含第一个不是目标车道的当前车道的信息,所以我可以稍后删除它们。
但是原始数据很大,并且有更多独特的Vehicle.ID。使用 for loop
似乎不是一个明智的主意。我怎样才能使用 dplyr
更快地达到同样的效果?
编辑 2(适合我的 dplyr 解决方案)
看来今天没有人在帮助心情。我想出了一个 dplyr
解决方案,如果有大约 8 个变道,可以应用该解决方案:
mydf %>%
mutate(ul = n_distinct(Lane),
target.lane.1 = unique(Lane)[ul - (ul-2)],
PVtl1 = Preceding.Vehicle.ID[match(target.lane.1, Lane)],
FVtl1 = Following.Vehicle.ID[match(target.lane.1, Lane)],
target.lane.2 = unique(Lane)[ul - (ul-3)],
PVtl2 = Preceding.Vehicle.ID[match(target.lane.2, Lane)],
FVtl2 = Following.Vehicle.ID[match(target.lane.2, Lane)],
target.lane.3 = unique(Lane)[ul - (ul-4)],
PVtl3 = Preceding.Vehicle.ID[match(target.lane.3, Lane)],
FVtl3 = Following.Vehicle.ID[match(target.lane.3, Lane)],
target.lane.4 = unique(Lane)[ul - (ul-5)],
PVtl4 = Preceding.Vehicle.ID[match(target.lane.4, Lane)],
FVtl4 = Following.Vehicle.ID[match(target.lane.4, Lane)],
target.lane.5 = unique(Lane)[ul - (ul-6)],
PVtl5 = Preceding.Vehicle.ID[match(target.lane.5, Lane)],
FVtl5 = Following.Vehicle.ID[match(target.lane.5, Lane)],
target.lane.6 = unique(Lane)[ul - (ul-7)],
PVtl6 = Preceding.Vehicle.ID[match(target.lane.6, Lane)],
FVtl6 = Following.Vehicle.ID[match(target.lane.6, Lane)],
target.lane.7 = unique(Lane)[ul - (ul-8)],
PVtl7 = Preceding.Vehicle.ID[match(target.lane.7, Lane)],
FVtl7 = Following.Vehicle.ID[match(target.lane.7, Lane)],
target.lane.8 = unique(Lane)[ul - (ul-9)],
PVtl8 = Preceding.Vehicle.ID[match(target.lane.8, Lane)],
FVtl8 = Following.Vehicle.ID[match(target.lane.8, Lane)],
target.lane.9 = unique(Lane)[ul - (ul-10)],
PVtl9 = Preceding.Vehicle.ID[match(target.lane.9, Lane)],
FVtl9 = Following.Vehicle.ID[match(target.lane.9, Lane)],
target.lane.final = unique(Lane)[ul],
PVtlf = Preceding.Vehicle.ID[match(target.lane.final, Lane)],
FVtlf = Following.Vehicle.ID[match(target.lane.final, Lane)])
不过,我想修改我的代码,以便根据观察到的变道次数创建新列。
我会通过创建一个包含新的感兴趣列的数据集来解决这个问题,然后使用 left_join
将新数据集连接回原始数据集。我将观察到的车道变更次数信息添加到数据集中,因此新列的数量可以基于观察到的车道变更次数。大部分工作是使用 tidyr
中的函数重塑数据集以创建新列 headers(使用 gather
和 unite
),然后创建新列(spread
)。我没有按所需顺序放置新列,但您当然可以这样做。
如果您有多个 Vehicle.ID
值,下面的代码应该有效。如果你只有一个 Vehicle.ID
你不需要 group_by
.
library(dplyr)
library(tidyr)
mydf %>%
filter(lane.change == "yes") %>%
group_by(Vehicle.ID) %>%
mutate(order = 1:n()) %>%
select(-Frame.ID, -lane.change) %>%
rename(target.lane = Lane, Pvtl = Preceding.Vehicle.ID, FVtl = Following.Vehicle.ID) %>%
gather(group, number, target.lane, Pvtl, FVtl) %>%
unite(group1, group, order, sep = "") %>%
spread(group1, number) %>%
left_join(mydf, .)
示例数据
mydf <- data.frame(Vehicle.ID = c(1,1,1,1,1,1,1,1), Frame.ID = c(1,2,3,4,5,6,7,8),
Lane = c(1,1,2,2,2,3,3,3), lane.change = c(".", ".", "yes", ".", ".","yes",".","."),
Preceding.Vehicle.ID = c(10,10,5,5,5,6,6,6),
Following.Vehicle.ID = c(20,20,50,50,50,30,30,30))
数据说明
Vehicle.ID:车辆ID
Frame.ID:帧数(1帧=0.1秒)
Lane: 当前占用的车道数
lane.change:“。”表示车辆在此帧中未变道,"yes"表示车辆在此帧中变道
Preceding.Vehicle.ID and Following.Vehicle.ID:当前车道前车和后车ID,在给定的框架中。
我想做的事情:
我要查找:
1. 车辆占用的所有车道。当前车道在 "Lane" 列中给出。车辆移动到的所有其他车道是目标车道。我想创建包含所有目标车道的车道编号的新列,即 target.lane1、target.lane2 等.
2. 同样,我想将所有前车 ID 和后车 ID 放入新列中,即目标车道 1 和 2 中的前车:PVtl1、PVtl2,以及目标车道 1 和 2 中的后车:FVtl1、FVtl2。
最终需要的数据框形式:
mydf.final <- mydf %>%
mutate(target.lane1 = 2, PVtl1 = 5, FVtl1 = 50,
target.lane2 = 3, PVtl2 = 6, FVtl2 = 30)
我尝试过的:
老实说,我不知道该怎么做。我尝试使用:
> mydf <- mydf %>%
+ mutate(pvtl1 = data.frame(unique(Preceding.Vehicle.ID)))
Error: not compatible with STRSXP
但如您所见,出现错误。
请指导我。我想为此使用 dplyr
。
编辑:
我已经尝试使用 for loop
并且它适用于此示例数据:
for (i in 1:length(unique(mydf$Lane))){
mydf[,paste("target.lane",i, sep=".")] = unique(mydf$Lane)[i]
mydf[,paste("PVtl",i, sep=".")] = unique(mydf$Preceding.Vehicle.ID)[i]
mydf[,paste("FVtl",i, sep=".")] = unique(mydf$Following.Vehicle.ID)[i]
}
在这里,target.lane.1、PVtl1 和 FVtl1 没有用,因为它们只包含第一个不是目标车道的当前车道的信息,所以我可以稍后删除它们。
但是原始数据很大,并且有更多独特的Vehicle.ID。使用 for loop
似乎不是一个明智的主意。我怎样才能使用 dplyr
更快地达到同样的效果?
编辑 2(适合我的 dplyr 解决方案)
看来今天没有人在帮助心情。我想出了一个 dplyr
解决方案,如果有大约 8 个变道,可以应用该解决方案:
mydf %>%
mutate(ul = n_distinct(Lane),
target.lane.1 = unique(Lane)[ul - (ul-2)],
PVtl1 = Preceding.Vehicle.ID[match(target.lane.1, Lane)],
FVtl1 = Following.Vehicle.ID[match(target.lane.1, Lane)],
target.lane.2 = unique(Lane)[ul - (ul-3)],
PVtl2 = Preceding.Vehicle.ID[match(target.lane.2, Lane)],
FVtl2 = Following.Vehicle.ID[match(target.lane.2, Lane)],
target.lane.3 = unique(Lane)[ul - (ul-4)],
PVtl3 = Preceding.Vehicle.ID[match(target.lane.3, Lane)],
FVtl3 = Following.Vehicle.ID[match(target.lane.3, Lane)],
target.lane.4 = unique(Lane)[ul - (ul-5)],
PVtl4 = Preceding.Vehicle.ID[match(target.lane.4, Lane)],
FVtl4 = Following.Vehicle.ID[match(target.lane.4, Lane)],
target.lane.5 = unique(Lane)[ul - (ul-6)],
PVtl5 = Preceding.Vehicle.ID[match(target.lane.5, Lane)],
FVtl5 = Following.Vehicle.ID[match(target.lane.5, Lane)],
target.lane.6 = unique(Lane)[ul - (ul-7)],
PVtl6 = Preceding.Vehicle.ID[match(target.lane.6, Lane)],
FVtl6 = Following.Vehicle.ID[match(target.lane.6, Lane)],
target.lane.7 = unique(Lane)[ul - (ul-8)],
PVtl7 = Preceding.Vehicle.ID[match(target.lane.7, Lane)],
FVtl7 = Following.Vehicle.ID[match(target.lane.7, Lane)],
target.lane.8 = unique(Lane)[ul - (ul-9)],
PVtl8 = Preceding.Vehicle.ID[match(target.lane.8, Lane)],
FVtl8 = Following.Vehicle.ID[match(target.lane.8, Lane)],
target.lane.9 = unique(Lane)[ul - (ul-10)],
PVtl9 = Preceding.Vehicle.ID[match(target.lane.9, Lane)],
FVtl9 = Following.Vehicle.ID[match(target.lane.9, Lane)],
target.lane.final = unique(Lane)[ul],
PVtlf = Preceding.Vehicle.ID[match(target.lane.final, Lane)],
FVtlf = Following.Vehicle.ID[match(target.lane.final, Lane)])
不过,我想修改我的代码,以便根据观察到的变道次数创建新列。
我会通过创建一个包含新的感兴趣列的数据集来解决这个问题,然后使用 left_join
将新数据集连接回原始数据集。我将观察到的车道变更次数信息添加到数据集中,因此新列的数量可以基于观察到的车道变更次数。大部分工作是使用 tidyr
中的函数重塑数据集以创建新列 headers(使用 gather
和 unite
),然后创建新列(spread
)。我没有按所需顺序放置新列,但您当然可以这样做。
如果您有多个 Vehicle.ID
值,下面的代码应该有效。如果你只有一个 Vehicle.ID
你不需要 group_by
.
library(dplyr)
library(tidyr)
mydf %>%
filter(lane.change == "yes") %>%
group_by(Vehicle.ID) %>%
mutate(order = 1:n()) %>%
select(-Frame.ID, -lane.change) %>%
rename(target.lane = Lane, Pvtl = Preceding.Vehicle.ID, FVtl = Following.Vehicle.ID) %>%
gather(group, number, target.lane, Pvtl, FVtl) %>%
unite(group1, group, order, sep = "") %>%
spread(group1, number) %>%
left_join(mydf, .)