【问题标题】:How do I select rows in a data frame before and after a condition is met?如何在满足条件之前和之后选择数据框中的行?
【发布时间】:2017-11-18 00:41:20
【问题描述】:

我现在在网上搜索了几天,但找不到解决我(可能很容易解决)问题的方法。

我有巨大的数据框,其中包含 4 个变量和超过一百万个观察值。现在我想在满足特定条件后选择 100 行,同时选择所有行和 1000 行,并用 NA 填充其余行。我用 for 循环和 if/ifelse 尝试了它,但到目前为止它不起作用。我认为这不应该是一件大事,但目前我只是不明白它的窍门。

我使用以下方法创建数据:

foo<-data.frame(t = 1:15, a = sample(1:15), b = c(1,1,1,1,1,4,4,4,4,1,1,1,1,1,1), c = sample(1:15))

我的数据如下所示:

ID    t   a   b   c
1     1   4   1   7
2     2   7   1   10
3     3   10  1   6
4     4   2   1   4
5     5   13  1   9
6     6   15  4   3
7     7   8   4   15
8     8   3   4   1
9     9   9   4   2
10   10   14  1   8
11   11   5   1   11
12   12   11  1   13
13   13   12  1   5
14   14   6   1   14
15   15   1   1   12

我想要的是选择a 的值(在此示例中)之前的 2 行、所有行以及之后的 3 行 b 的值 >1 并用 NA 填充其余部分。 [因为这只是一个例子,我猜你可以想象在这 15 行之后,还有更多的行,b 的值从 1 变为 4 几次(我没有发布它,所以我不会发送垃圾邮件问题有不必要的数据)。] 所以我想得到类似的东西:

ID    t   a   b   c   d
1     1   4   1   7  NA
2     2   7   1   10 NA 
3     3   10  1   6  NA 
4     4   2   1   4   2
5     5   13  1   9  13 
6     6   15  4   3  15 
7     7   8   4   15  8
8     8   3   4   1   3
9     9   9   4   2   9
10   10   14  1   8  14 
11   11   5   1   11  5
12   12   11  1   13 11 
13   13   12  1   5  NA 
14   14   6   1   14 NA 
15   15   1   1   12 NA 

感谢您的帮助。

谢谢。

最好的问候, 克里斯

【问题讨论】:

  • 我不明白这个问题。大概d 列基于您的“条件”,但d 列与a 列相同,除了它的第一个和最后一个条目,不是吗? b 在这里如何发挥作用?你能澄清一下你具体例子的情况吗?
  • 很抱歉,这是我的第一个问题。我尽量减少示例中的数据,所以恐怕看起来不太合理。我的数据来自实验,其中b 是一个打开 (4) 和关闭 (1) 的 LED,我想在 LED 开启之前计算 a 的 10 个值的滚动平均值(100 个值),当它打开时,LED 关闭后有 1000 个值。当有 100 万个观测值时,它看起来会有所不同。
  • 如果@missuse 的回答不能解决您的问题,您能否举一个具有代表性的最小示例,在其中说明您的测试用例的条件和预期的结果。我想这将有助于向 SO 社区澄清您的问题。
  • 我稍微编辑了这个问题。

标签: r dataframe


【解决方案1】:

这是一个尝试。

获取满足条件b &gt; 1的索引

z <- which(foo$b > 1)

获取(z - 2) : (z + 3)的索引

ind <- unique(unlist(lapply(z, function(x){
  g <- pmax(x - 2, 1) #if x - 2 is negative
  g : (x + 3)
})))

创建用NA填充的d

foo$d <- NA

foo$a替换适当索引的元素

foo$d[ind] <- foo$a[ind]

【讨论】:

  • 谢谢!我认为这应该很好用,不幸的是它现在还没有真正的数据。但我会解决的。起初它是错误only 0's may be mixed with negative subscripts,在我对数据帧进行子集化以稍微减少它之后,它给出了一个替换错误,我还不明白。但是您的解决方案让我向前迈出了一步!
  • @Chris 如果您可以提供数据,我不介意下载 50 万行来尝试提供解决方案。检查它现在是否有效。我在lapply 调用中添加了一个附加条件。
  • 前几天忙着应付生活,现在又有时间工作了。 :D 非常感谢@missuse!您的回答帮助我解决了问题。起初我遇到了替换会比实际数据框大的问题(由于我的真实数据中有 +1000 行)。在示例中,它将等同于x+7。我现在解决了。我添加了h &lt;- ifelse(x+7 &gt; nrow(foo), nrow(foo), x+7,然后添加了g:h。如果这是一个好的解决方案,我不会,但现在我很满意。
【解决方案2】:

这里是与 misuse 相同的尝试,但使用 data.table:

library(data.table)
foo<-data.frame(t = 1:11, a = sample(1:11), b = c(1,1,1,4,4,4,4,1,1,1,1), c = sample(1:11))
DT <- setDT(foo)
DT[ unique(c(DT[,.I[b>1] ],DT[,.I[b>1]+3 ],DT[,.I[b>1]-2 ])), d := a]

     t  a b  c  d
 1:  1 10 1  2 NA
 2:  2  6 1 10  6
 3:  3  5 1  7  5
 4:  4 11 4  4 11
 5:  5  4 4  9  4
 6:  6  8 4  5  8
 7:  7  2 4  8  2
 8:  8  3 1  3  3
 9:  9  7 1  6  7
10: 10  9 1  1  9
11: 11  1 1 11 NA

这里

unique(c(DT[,.I[b>1] ],DT[,.I[b>1]+3 ],DT[,.I[b>1]-2 ]))

为您提供所需的索引:根据您的情况,行的唯一索引,相同的索引 +3 和 -2。

【讨论】:

  • 感谢您的回答。可悲的是,它说我超出了范围。所以它不起作用。
【解决方案3】:
library(dplyr)
library(purrr)

# example dataset
foo<-data.frame(t = 1:15, 
                a = sample(1:15), 
                b = c(1,1,1,1,1,4,4,4,4,1,1,1,1,1,1), 
                c = sample(1:15))

# function to get indices of interest
# for a given index x go 2 positions back and 3 forward
# keep only positive indices
GetIDsBeforeAfter = function(x) {
  v = (x-2) : (x+3)
  v[v > 0]
}


foo %>%                        # from your dataset
  filter(b > 1) %>%            # keep rows where b > 1
  pull(t) %>%                  # get the positions
  map(GetIDsBeforeAfter) %>%   # for each position apply the function
  unlist() %>%                 # unlist all sets indices
  unique() -> ids_to_remain    # keep unique ones and save them in a vector

foo$d = foo$c                  # copy column c as d
foo$d[-ids_to_remain] = NA     # put NA to all positions not in our vector

foo  

#     t  a b  c  d
# 1   1  5 1  8 NA
# 2   2  6 1 14 NA
# 3   3  4 1 10 NA
# 4   4  1 1  7  7
# 5   5 10 1  5  5
# 6   6  8 4  9  9
# 7   7  9 4 15 15
# 8   8  3 4  6  6
# 9   9  7 4  2  2
# 10 10 12 1  3  3
# 11 11 11 1  1  1
# 12 12 15 1  4  4
# 13 13 14 1 11 NA
# 14 14 13 1 13 NA
# 15 15  2 1 12 NA

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-16
    • 2020-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-11
    • 2021-11-14
    • 2022-12-08
    相关资源
    最近更新 更多