R - 在滑动窗口中返回max或min值的数据表行号

时间:2016-04-20 01:18:51

标签: r max row-number sliding-window

我正在尝试检索与滑动窗口中的最大/最小值关联的行号。我然后对该行号进行子集化以从不同的列中检索值。

根据您的要求,这是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 + 90]中与Average [i]的最大正偏差。 NegativeChange是[i:i + 90]中与Average [i]的最大负偏差。 EndTimestamp,以及为什么我试图找到Max / Min值的行号,应该是 max 平均值最高的时间戳[i:i + 90] min 平均值最低的时间戳[i:i + 90] 。我尝试仅在PositiveChange&gt; = 1或NegativeChange&lt; = -1时触发EndTimestamp功能。

我尝试查找最大值行号的代码示例如下:

#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&gt; = 1的最大值,并且在转换为查找NegativeChange&lt; = -1的min时似乎更糟。由于数据的性质,其中Average> = 1的顺序行在大多数情况下应该具有相同的结束时间戳。但上面的代码会产生升序时间戳。并且在某一点(第928行到第973行)产生下降的时间戳,这没有任何意义。

我确信有一个简单的答案,但对于R和编码新手而言,我花了好几个小时试图找到它无济于事。

此外,z变量是为了纠正which和which.max函数根据被检查的范围返回索引值的事实(我认为)。因此,如果500:600中的最大值位于数据表的504行中,那么哪些函数将返回值4.有没有办法解决这个问题,以便返回504?

连连呢?很高兴在需要时提供更多信息。

1 个答案:

答案 0 :(得分:0)

我不了解您的代码的目的,为什么需要移动窗口聚合?也许有一种更适合您问题的数据结构。但是,使用给定的数据,我建议如下:

&#34; NegativeChange&#34;是给定间隔内平均值的最小偏差。根据定义,这是每个间隔的最小值。 您正在移动窗口中查找最小(最大)值。包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])
}