R - вернуть номер строки данных с указанием максимального или минимального значения в скользящем окне

Я пытаюсь получить номер строки, связанный со значением max/min в скользящем окне. Затем я подставляю номер строки, чтобы получить значение из другого столбца.

По вашему запросу вот dput(head(DATAFRAME3)):

structure(list(Time = c("00:00:01|", "00:00:03|", "00:00:04|", 
"00:00:05|", "00:00:06|", "00:00:07|"), Average = c(8, 5.75, 
5.33333333333333, 5.23076923076923, 5.15, 5.15), NegativeChange = c(-3, 
-0.75, -0.333333333333333, -0.230769230769231, -0.15, -0.15), 
    PositiveChange = c(0, 0, 0.107843137254902, 0.210407239819005, 
    0.291176470588235, 0.291176470588235)), .Names = c("Time", 
"Average", "NegativeChange", "PositiveChange"), class = c("data.table", 
"data.frame"), row.names = c(NA, -6L), .internal.selfref = <pointer: 0x0000000001300788>)

Вот загрузка усеченного файла текстовых данных, а затем кода, который я использовал, чтобы импортировать его в R и получить его до того места, где я пытался закодировать часть End Timestamp:

http://textuploader.com/5ymml

Код:

#prepare workspace...delete prior data and values
rm(list=ls())

#Load packages
library(data.table)
library(dplyr)

#set working directory, setwd(filepath)
setwd()

#load fixed width data, n = 39
DATAFRAME <- read.fwf("Dataframe3_Truncated.txt", widths = c(9,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1), header = FALSE, sep = "\t", skip = 4, na.strings = c("-"))

#transform to data.table
DATAFRAME <- data.table(DATAFRAME)

#Calculate row averages, adding an "Average" column to the data set
DATAFRAME2 <- DATAFRAME[, .(Average = rowMeans(.SD, na.rm = TRUE)), "V1"]

#Calculate NegativeChange and PositiveChange using subscript method
NegativeChange <- numeric(nrow(DATAFRAME2))
PositiveChange <- numeric(nrow(DATAFRAME2))
for (i in 1:(nrow(DATAFRAME2)-90)) {
  y <- i
  x <- i+90
  NegativeChange[i] <- min(DATAFRAME2$Average[y:x]) - DATAFRAME2$Average[i]
  PositiveChange[i] <- max(DATAFRAME2$Average[y:x]) - DATAFRAME2$Average[i]
 }

#add NegativeChange and PositiveChange columns to datatable
DATAFRAME3 <- DATAFRAME2[, .(Time = as.character(V1), Average, NegativeChange, PositiveChange)]
DATAFRAME3

PositiveChange - максимальное положительное отклонение от среднего значения [i] в ​​[i:i + 90]. NegativeChange - максимальное отрицательное отклонение от среднего значения [i] в ​​[i: i + 90]. EndTimestamp, и почему я пытаюсь найти номер строки для значения Max/Min, должен быть для max отметка времени, при которой среднее значение является самым высоким [i: i + 90], и для min отметка времени, при которой среднее значение равно самый низкий [я: я + 90]. Я пытался заставить функцию EndTimestamp срабатывать только тогда, когда PositiveChange >= 1 или NegativeChange <= -1.

Ниже приведены примеры кода, в котором я пытался найти номер строки максимального значения:

#which.max
EndTimestamp <- numeric(nrow(DATAFRAME3))
for (i in seq(nrow(DATAFRAME3))) {
  X <- (i + 1)
  y <- (i + 91)
  z <- (i)
  if (DATAFRAME3$PositiveChange[i] >= 1) {
    EndTimestamp[i] <- DATAFRAME3[(which.max(DATAFRAME3$Average[x:y]) + z), Time]
  } else {
    EndTimestamp[i] <- NA
  }
}  



#which
TimestampRowIndex <- c()
TimestampRowActual <- c()
EndTimestamp3 <- numeric(nrow(DATAFRAME3))
for (i in seq(nrow(DATAFRAME3))) {
  X <- (i + 1)
  y <- (i + 91)
  z <- (i)
  if (DATAFRAME3$PositiveChange[i] >= 1) {
    TimestampRowIndex <- append(TimestampRowIndex, which(DATAFRAME3$Average[x:y] == max(DATAFRAME3$Average[x:y])))
    TimestampRowActual <- TimestampRowIndex[length(TimestampRowIndex)] + z
    EndTimestamp3[i] <- DATAFRAME3[as.integer(TimestampRowActual), Time]
  } else {
    EndTimestamp3[i] <- NA
  }
}

Ни одно из решений не работает для нахождения максимума для PositiveChange >= 1, и, похоже, работает хуже при преобразовании, чтобы найти минимум для NegativeChange <= -1. Из-за характера данных последовательные строки, в которых Среднее>= 1, в большинстве случаев должны иметь одинаковую отметку времени окончания. Но приведенный выше код создает восходящие временные метки. И в один момент (строки с 928 по 973) выдает нисходящие временные метки, что не имеет смысла.

Я уверен, что есть простой ответ, но, будучи новичком в R и кодировании в целом, я потратил часы, пытаясь найти его безрезультатно.

Кроме того, переменная z должна исправить тот факт, что функции which и which.max возвращают значение индекса на основе исследуемого диапазона (я думаю). Так что, если максимальное значение в 500:600 находится в строке 504 таблицы данных, функции which вернут значение 4. Есть ли способ обойти это, чтобы он возвращал 504?

Предложения? Рад предоставить больше информации, если это необходимо.

1 ответ

Решение

Я не понимаю цель вашего кода, зачем вам перемещать агрегаты окон? Может быть, есть структура данных, более подходящая для вашей проблемы. Однако, используя приведенные данные, я предлагаю следующее:

"NegativeChange" - это минимальное отклонение от среднего за данный интервал. Это по определению минимальное значение за интервал. Вы ищете минимальные (максимальные) значения в движущемся окне. Пакет RcppRoll предоставляет полезные функции для этой задачи:

library(RcppRoll)
DATAFRAME2$min_Average = roll_minl(Average, 90)
DATAFRAME2$max_Average = roll_maxl(Average, 90)

На следующем шаге вы пытаетесь получить номер строки (или позицию в интервале?) Минимального / максимального значения за интервал. Если вам нужна эта информация, вам, вероятно, придется использовать цикл.

#Calculate row averages, adding an "Average" column to the data set
DATAFRAME2 <- DATAFRAME[, .(Average = rowMeans(.SD, na.rm = TRUE)), "V1"]

# calculate min/max of rolling Window
for (i in 1:nrow(DATAFRAME2)) {
    j = min(i+90, nrow(DATAFRAME2)) # upper bound of window
    DATAFRAME2$min_Average[i] = min(DATAFRAME2$Average[i:j])
    DATAFRAME2$pos_min_Average[i] = (i-1) + which.min(DATAFRAME2$Average[i:j])
    DATAFRAME2$max_Average[i] = max(DATAFRAME2$Average[i:j])
    DATAFRAME2$pos_max_Average[i] = (i-1) + which.max(DATAFRAME2$Average[i:j])
}
Другие вопросы по тегам