【问题标题】:filtering observations from time series conditionally by group按组有条件地过滤来自时间序列的观察
【发布时间】:2018-12-11 02:16:21
【问题描述】:

我有一个包含多个时间序列(值~时间)的 df(“df”),其观察结果按 3 个因素分组:温度、代表和物种。这些数据需要在时间序列的上下端进行修剪,但这些阈值是有条件的(例如,删除低于 2 和高于 10 的观察值,其中 temp=10、rep=2 和 species =“A”)。 我有一个随附的 df (df_thresholds),其中包含分组值以及我想为每个组使用的最小值和最大值。并非所有组都需要修剪(我想定期更新此文件,以指导修剪 df 的位置)。 谁能帮我按组有条件地过滤掉这些值?我有以下,很接近但不完全在那里。当我反转最大和最小布尔测试时,我得到零观察值。

df <- data.frame(species = c(rep("A", 16), rep("B", 16)),
                 temp=as.factor(c(rep(10,4),rep(20,4),rep(10,4),rep(20,4))),
                 rep=as.factor(c(rep(1,8),rep(2,8),rep(1,8),rep(2,8))),
                 time=rep(seq(1:4),4),
                 value=c(1,4,8,16,2,4,9,16,2,4,10,16,2,4,15,16,2,4,6,16,1,4,8,16,1,2,8,16,2,3,4,16))

df_thresholds <- data.frame(species=c("A", "A", "B"), 
                            temp=as.factor(c(10,20,10)),
                            rep=as.factor(c(1,1,2)), 
                            min_value=c(2,4,2),
                            max_value=c(10,10,9))

#desired outcome
df_desired <- df[c(2:3,6:7,9:24,26:27,29:nrow(df)),]


#attempt
df2 <- df

for (i in 1:nrow(df_thresholds)) {  
  df2 <- df2 %>%
    filter(!(species==df_thresholds$species[i] & temp==df_thresholds$temp[i] & rep==df_thresholds$rep[i] & value>df_thresholds$min_value[i] & value<df_thresholds$max_value[i]))
}

编辑:这是我根据以下建议实施的解决方案。

df_test <- left_join(df, df_thresholds, by=c('species','temp','rep'))
df_test$min_value[is.na(df_test$min_value)] <- 0
df_test$max_value[is.na(df_test$max_value)] <- 999

df_test2 <- df_test %>%
  filter(value >= min_value & value <= max_value)

【问题讨论】:

  • 我不确定预期的结果应该是什么,但一个选项可能是将两个 df 与 left_join 连接起来,并将您的过滤器应用于生成的 df df_test &lt;- left_join(df, df_thresholds, by=c("species", 'temp', 'rep')) %&gt;% filter(value &gt; min_value &amp; value &lt; max_value )
  • 您可以使用data.table::foverlaps,使用此功能您可以(快速!)执行重叠连接...阅读本主题中的答案:stackoverflow.com/questions/24480031/…
  • 我添加了期望的结果,但我想指出我想通过约束时间变量而不是值来进行子集化。
  • @NColl,非常感谢。通过将我的限制加入 df 并过滤值变量,我排除了我想要的所有内容。

标签: r filter tidyr


【解决方案1】:

我们可以使用mapply找出我们想要排除的索引

df[-c(with(df_thresholds, 
      mapply(function(x, y, z, min_x, max_x) 
           which(df$species == x & df$temp == y & df$rep == z & 
              (df$value < min_x | df$value > max_x)),
                 species, temp, rep, min_value, max_value))), ]


#   species temp rep time value
#2        A   10   1    2     4
#3        A   10   1    3     8
#6        A   20   1    2     4
#7        A   20   1    3     9
#9        A   10   2    1     2
#10       A   10   2    2     4
#11       A   10   2    3    10
#12       A   10   2    4    16
#......

mapply 中,我们相应地传递df_thresholds 过滤df 的所有列,并找出每行的最小值和最大值之外的索引,并将它们从原始数据帧中排除。

mapply调用的结果是

#[1]  1  4  5  8 25 28

哪些是我们想要从df 中排除的行,因为它们超出了范围。

【讨论】:

  • 我收到了您发布的输出,但它不适用于我的实际数据集。我的分组变量需要是因子,还是可以是数字、整数或字符?另外,如果每组的观察次数不同,这会影响您的答案吗?
  • @bishopia 不,分组变量可以是任何东西,它应该仍然有效。你能告诉我在你的实际数据集中什么不起作用吗?它会给你更多的行吗?或更少的行还是给你任何错误?
  • "-c(with(yy, mapply(function(x, y, z, min_x, max_x) which(xx$ref == : 对一元运算符无效的参数) 中的错误。我更改了"物种”到“参考”
  • @bishopia 你能删除df[-c( 部分并运行代码吗?您是否获得如上例所示的行索引?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-26
  • 1970-01-01
  • 2020-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多