R - 根据带有 lag() 的重复虚拟变量调整起始变量 - 每行多次测量
R - adjust start variable based on repeating dummy variable with lag() - multiple measurement per row
在我的数据中,如果虚拟变量重复,我想连续调整起始变量:
我有如下数据(自己添加了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 行中看到多个测量值放在一行中。例如,第二次测量在第一次测量开始 + 第一次测量持续时间之后开始。
我已经用 separate_rows
和 left_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 将是正常启动,它可能会工作,因为我们将有一个第一个值开始......)。 (如果我使用正常的起始列,它对多行的第二次测量是正确的。)
也许我应该以不同的方式处理它,即使用应用功能?感谢您的帮助,如果您对如何使我的问题更清楚有什么建议,请告诉我。
像这样?
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
在我的数据中,如果虚拟变量重复,我想连续调整起始变量:
我有如下数据(自己添加了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 行中看到多个测量值放在一行中。例如,第二次测量在第一次测量开始 + 第一次测量持续时间之后开始。
我已经用 separate_rows
和 left_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 将是正常启动,它可能会工作,因为我们将有一个第一个值开始......)。 (如果我使用正常的起始列,它对多行的第二次测量是正确的。)
也许我应该以不同的方式处理它,即使用应用功能?感谢您的帮助,如果您对如何使我的问题更清楚有什么建议,请告诉我。
像这样?
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