【问题标题】:How to label a specific range of values in R?如何在 R 中标记特定范围的值?
【发布时间】:2017-06-29 14:58:06
【问题描述】:

数据

我的原始数据框包含有关不同驾驶员变道的信息。每个司机多次变换车道。我创建了一个列lane.change,其中包含yes 在车道改变的点。以下是一个示例数据帧,其中包含单个驾驶员的 2 次车道变换:

x <- structure(list(file.ID = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L), class = "factor", .Label = "Car1"), frames = 1:11, 
    lane.change = structure(c(1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 
    1L, 1L, 1L), .Label = c("no", "yes"), class = "factor"), 
    y.m = c(80, 80, 80, 81, 82, 82, 82, 83, 84, 84, 84)), row.names = c(NA, 
-11L), class = "data.frame", .Names = c("file.ID", "frames", 
"lane.change", "y.m"))

变道图:

LC1LC2 行显示了这些数据中的车道变化范围。

我想做什么:

我想标记图中显示的值范围。这表示变道的完整持续时间。所以,我想要的输出是:

期望的输出:

> x
   file.ID frames lane.change range_LC y.m
1     Car1      1          no        .  80
2     Car1      2          no        .  80
3     Car1      3          no      LC1  80
4     Car1      4         yes      LC1  81
5     Car1      5          no      LC1  82
6     Car1      6          no        .  82
7     Car1      7          no      LC2  82
8     Car1      8         yes      LC2  83
9     Car1      9          no      LC2  84
10    Car1     10          no        .  84
11    Car1     11          no        .  84

我的尝试和问题:

我知道我可以使用x[which(x$lane.change=="yes"),"frames"] 引用相关的frames。但目标是为每次换道标记上一行和下一行。我被困在如何做到这一点上。另外,我想将它应用于所有司机(在原始数据中),每个司机都有不同的车道改变次数(>=2)。请指导我使用什么功能。我更喜欢使用dplyrpurrr。提前致谢。

【问题讨论】:

    标签: r


    【解决方案1】:

    首先我会创建一些辅助函数

    is_changing <- function(x) {
      x !=lag(x, default=first(x)) | x != lead(x, default=last(x))
    }
    

    这个函数主要是查看向量中的任何特定值是否靠近不同的值(增加或减少)。

    下一个函数采用 TRUE/FALSE 值向量,并为每次运行的 TRUE 值分配一个新索引。

    true_run_index <- function(x) {
      r<-rle(x)
      v<-r$values
      v[v] <- seq.int(sum(v))
      v[v==0]<-NA
      rep(v, r$length)
    }
    

    然后我们可以将它们与您的示例数据一起使用

    x %>% mutate(LC = true_run_index(is_changing(lane.change)))
    x %>% mutate(LC = true_run_index(is_changing(y.m)))
    
    #    file.ID frames lane.change y.m LC
    # 1     Car1      1          no  80 NA
    # 2     Car1      2          no  80 NA
    # 3     Car1      3          no  80  1
    # 4     Car1      4         yes  81  1
    # 5     Car1      5          no  82  1
    # 6     Car1      6          no  82 NA
    # 7     Car1      7          no  82  2
    # 8     Car1      8         yes  83  2
    # 9     Car1      9          no  84  2
    # 10    Car1     10          no  84 NA
    # 11    Car1     11          no  84 NA
    

    【讨论】:

    • 感谢您的解决方案。如果我想在lane.change=="yes" 行之前和之后标记 2 或 any 行怎么办?我尝试使用lag(x, 2, default=first(x)),但它没有正确标记之后的 2 行。
    • lead()lag() 旨在提取单个值。如果你想围绕一个值提取一个更大的集合,那么你可能不得不编写另一个帮助函数来为你做这件事。您也许可以使用embed 命令的一个版本,但这会使在向量末端的工作更加困难。与您最初描述的问题相比,这确实是一种不同类型的问题。
    • 你是对的。实际上,我发现对于我的原始数据,我需要在 lane.change=="yes" 行之前标记 800 行,在之后标记 800 行。我可以编辑这个问题吗?
    • 这足以证明打开一个新问题是合理的。问题得到回答后,您不应对其进行有意义的更改。
    【解决方案2】:

    使用dplyrdata.table 中的函数的解决方案。 x4 是最终输出。

    library(dplyr)
    library(data.table)
    
    x2 <- x %>%
      mutate(LC_ID = rleid(lane.change)/2) %>%
      mutate(LC_ID2 = ifelse(LC_ID %% 1 == 0, paste0("LC", LC_ID), NA)) %>%
      mutate(LC_ID3 = lag(LC_ID2), LC_ID4 = lead(LC_ID2))
    
    x3 <- mutate(x2, range_LC = coalesce(x2$LC_ID2, x2$LC_ID3, x2$LC_ID4, "."))
    
    x4 <- x3 %>% select(file.ID, frames, lane.change, range_LC, y.m)
    

    【讨论】:

    • 感谢您的解决方案。但是正如我在对@MrFlick 的回答的评论中提到的那样,如果我想在lane.change=="yes" 行之前和之后标记任意数量的行怎么办?在您的解决方案中,我将leadlag 函数中的参数n 更改为2。之后,我尝试了x4 %&gt;% tidyr::fill(range_LC, .direction = "down"),但它什么也没做。有什么建议吗?
    • 我同意@MrFlick。你在问一个新问题。考虑发一个新帖子。
    猜你喜欢
    • 2017-12-03
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-27
    • 2021-06-22
    相关资源
    最近更新 更多