【问题标题】:R - adjust start variable based on repeating dummy variable with lag() - multiple measurement per rowR - 基于重复虚拟变量调整起始变量,带有 lag() - 每行多次测量
【发布时间】:2023-04-04 00:15:02
【问题描述】:

在我的数据中,如果虚拟变量重复,我想连续调整起始变量:

我有如下数据(我自己添加了rcount变量):

head(elevation_raw)

                start         duration       value     rcount
1 2021-02-20 12:41:00             [60]         [0]       1
2 2021-02-20 12:49:00       [60,20,37]     [0,0,0]       2
3 2021-02-20 12:57:00             [60]         [0]       3
4 2021-02-20 13:02:00             [60]         [0]       4
5 2021-02-20 13:09:00 [60,60,60,60,60] [0,0,0,0,0]       5
6 2021-02-20 14:19:00          [60,60]       [0,0]       6

您会看到测量的开始、测量的持续时间(测量持续多长时间,也表示测量的结束)和值(此处为高程)。

您可以在第 1、5、6 行看到多个测量值放在一行中。例如,第 2 次测量在第一次开始 + 第一次的持续时间之后开始。

我已经用separate_rowsleft_join 将数据放在了很好的行中,但是“多重测量”行的开头是错误的。请注意,当 rcount 重复时,可以找到这些多个测量行:

durations <-  separate_rows(elevation_raw, duration, sep = ",", convert=T) %>%
  select( c(-value)) 
durations <- mutate(durations, rcount2 = as.numeric(rownames(durations)))

values <-  separate_rows(elevation_raw, value, sep = ",", convert=T) %>%
  select( -c(duration))
values <- mutate(values, rcount2 = as.numeric(rownames(values)))

elevation_raw <-left_join(durations, values, by=c('rcount2', 'rcount', "start")) 

#result:
head(elevation_raw)
# A tibble: 6 x 6
  start               duration   rcount rcount2 value
  <dttm>                 <int>   <dbl>   <dbl> <int>
1 2021-02-20 12:41:00       60   1       1     0
2 2021-02-20 12:49:00       60   2       2     0       #"multiple measurement" row, see rcount
3 2021-02-20 12:49:00       20   2       3     0       #"multiple measurement" row
4 2021-02-20 12:49:00       37   2       4     0       #"multiple measurement" row
5 2021-02-20 12:57:00       60   3       5     0
6 2021-02-20 13:02:00       60   4       6     0

当然,我想添加一个包含真实开始的列,因为现在“多次测量”行的开始不正确。我尝试了以下方法:

elevation_raw<- mutate(elevation_raw, real_start=ifelse(rcount==dplyr::lag(rcount), 
                  dplyr::lag(elevation_raw$real_start)+dplyr::lag(elevation_raw$duration), elevation_raw$start) )

如果 rcount 重复(使用 (rcount==lag(rcount) ),则实际行的真正开始是上一行的真正开始 + 上一行的持续时间。否则与正常启动相同。 当然,这种方法不起作用:我不能使用我现在正在构建的列来构建列(尽管我认为如果第一行不是多重测量行,real_start 将是正常的开始,并且它可能会起作用,因为我们将有一个开始的第一个值......)。 (如果我使用正常的起始列,它对于多行的第二次测量是正确的。)

也许我应该以不同的方式处理它,即使用 apply 函数?感谢您的帮助,如果您对如何使我的问题更清楚有任何建议,请告诉我。

【问题讨论】:

    标签: r dplyr apply data-cleaning tapply


    【解决方案1】:

    像这样?

    library(data.table)
    library(stringr)
    # Sample data
    DT <- fread("
                    start         duration       value     rcount
    2021-02-20T12:41:00             [60]         [0]       1
    2021-02-20T12:49:00       [60,20,37]     [0,0,0]       2
    2021-02-20T12:57:00             [60]         [0]       3
    2021-02-20T13:02:00             [60]         [0]       4
    2021-02-20T13:09:00 [60,60,60,60,60] [0,0,0,0,0]       5
    2021-02-20T14:19:00          [60,60]       [0,0]       6")
    DT[, start := as.POSIXct(start, format = "%Y-%m-%dT%H:%M:%S")]
    # maximum number of duration/values
    ncols <- length(tstrsplit(DT$duration, ","))
    # split the durarion and value columns
    DT[, paste0("duration", 1:ncols) := lapply(transpose(str_extract_all(duration, "\\d+")), as.numeric)]
    DT[, paste0("value", 1:ncols) := lapply(transpose(str_extract_all(value, "\\d+")), as.numeric)]
    # For decimal values, replace the line above with the following line
    # DT[, paste0("value", 1:ncols) := lapply(transpose(str_extract_all(value, "[0-9]\\d*(\\.\\d+)?")), as.numeric)]
    # Driop the original value and durarion columns
    DT[, `:=`(duration = NULL, value = NULL)]
    answer <- melt(DT, measure.vars = patterns(duration = "^duration[0-9]",value = "^value[0-9]"),na.rm = TRUE)
    # Order
    setkey(answer, rcount, variable)
    # start addition = cumulative sum of durations
    answer[, start_new := start + (cumsum(duration) - duration[1]), by = .(rcount)][]
    #                  start rcount variable duration value           start_new
    # 1: 2021-02-20 12:41:00      1        1       60     0 2021-02-20 12:41:00
    # 2: 2021-02-20 12:49:00      2        1       60     0 2021-02-20 12:49:00
    # 3: 2021-02-20 12:49:00      2        2       20     0 2021-02-20 12:49:20
    # 4: 2021-02-20 12:49:00      2        3       37     0 2021-02-20 12:49:57
    # 5: 2021-02-20 12:57:00      3        1       60     0 2021-02-20 12:57:00
    # 6: 2021-02-20 13:02:00      4        1       60     0 2021-02-20 13:02:00
    # 7: 2021-02-20 13:09:00      5        1       60     0 2021-02-20 13:09:00
    # 8: 2021-02-20 13:09:00      5        2       60     0 2021-02-20 13:10:00
    # 9: 2021-02-20 13:09:00      5        3       60     0 2021-02-20 13:11:00
    #10: 2021-02-20 13:09:00      5        4       60     0 2021-02-20 13:12:00
    #11: 2021-02-20 13:09:00      5        5       60     0 2021-02-20 13:13:00
    #12: 2021-02-20 14:19:00      6        1       60     0 2021-02-20 14:19:00
    #13: 2021-02-20 14:19:00      6        2       60     0 2021-02-20 14:20:00
    

    【讨论】:

    • 感谢您的回答!我有一些困惑,我只想使用上面非常有用的代码与 ppl 分享:不要忘记将数据转换为 data.table (DT&lt;-as.data.table(df)),(在加载 data.tablestringr 旁边) .也许其他初学者会监督这一点,或者在data.table 中也不太流利,并且还会遇到一些错误
    • 我有另一个类似的数据集,“值 col”如下所示:[0.88,0.24,0.28](请注意新的小数位)。因此,在“融化”行(融化为“答案”)中,patterns 找不到 "^value[0-9]",因为有小数位。我自己找不到灵魂……我应该编辑我的问题还是开始一个新问题?谢谢
    • 您需要一个正则表达式来捕获数值,包括小数点和之后的数值(如果有)。这应该工作DT[, paste0("value", 1:ncols) := lapply(transpose(str_extract_all(value, "[0-9]\\d*(\\.\\d+)?")), as.numeric)]。另外,请参阅上面答案中的编辑。
    猜你喜欢
    • 2017-05-31
    • 1970-01-01
    • 2022-12-02
    • 1970-01-01
    • 1970-01-01
    • 2022-07-31
    • 2015-09-23
    • 2023-03-14
    • 2015-08-17
    相关资源
    最近更新 更多