【问题标题】:How to compress/delete rows with conditions in R?如何在 R 中使用条件压缩/删除行?
【发布时间】:2017-05-24 10:03:49
【问题描述】:

我有一个数据框,请看下面。如何在某些条件下压缩/删除行?我只想在 V1 中有连续的1 时选择最高的音量

例如:df[2:5,]V1 都等于1,其中最大的音量是df[4,] 所以删除df[c(2,3,5),],对于df[9:10,],这两个的最大音量是df[10,] , 删除 df[9,]..... 以此类推....结果会像 Example Picture 其中V1 会像 0101010101....

如何在不使用循环的情况下实现这一点,如何以矢量化方式实现这一点,以便计算速度更快(处理数百万行时)?

更新: 我使用V2 应用相同的循环,但仅在 Volume 小于时删除,这就是示例图片中第 13 行被删除的原因,因为第 13 行的体积小于第 14 行的体积。

更新(另一个问题): 我试过akrun的方法,我从组中选择最大值Volume,但是当有两个或更多最大值时,仍然会有一个连续的1,就像下面的row 9一样。如何删除重复的行? 我可以使用 duplicated(df$Volume) ,还有其他方法吗?谢谢

更新: 跟进 akrun 的尝试,代码将删除 V1==0 所在的行,这不是我想要的,我只想在 V1==1 并且 Volume 小于该组的最大 Volume 时删除。我知道这将在V1 中有一些连续的 0,并且删除 V1 中的重复 0 将取决于 Weight 所以这就是为什么我只需要删除 V1==1 而不能删除 V1==0

#   Volume Weight V1 V2
#1  0.5367 0.5367  0  1
#4  1.1457 1.1413  1  0
#6  0.5694 0.5633  0  1
#7  1.2368 1.2343  1  0
#8  0.9662 0.9593  0  1
#9  1.4102 1.3923  1  0
#10 1.4102 1.3995  1  0
#11 1.1132 1.1069  0  1
#12 1.4535 1.3923  1  0
#14 1.1475 1.1447  0  1
#15 1.1790 1.1748  1  0
#18 1.1557 1.1552  0  1

数据框 df

    Volume Weight V1 V2 
 1: 0.5367 0.5367  0  1
 2: 0.8645 0.8508  1  0
 3: 0.8590 0.8585  1  0
 4: 1.1457 1.1413  1  0
 5: 0.8573 0.8568  1  0
 6: 0.5694 0.5633  0  1
 7: 1.2368 1.2343  1  0
 8: 0.9662 0.9593  0  1
 9: 1.3550 1.3412  1  0
10: 1.4102 1.3995  1  0
11: 1.1132 1.1069  0  1
12: 1.4535 1.3923  1  0
13: 1.0437 1.0344  0  1
14: 1.1475 1.1447  0  1
15: 1.1790 1.1748  1  0
16: 1.1749 1.1735  1  0
17: 1.1749 1.1731  1  0
18: 1.1557 1.1552  0  1

示例图片

    Volume Weight V1 V2 
 1: 0.5367 0.5367  0  1
 4: 1.1457 1.1413  1  0
 6: 0.5694 0.5633  0  1
 7: 1.2368 1.2343  1  0
 8: 0.9662 0.9593  0  1
10: 1.4102 1.3995  1  0
11: 1.1132 1.1069  0  1
12: 1.4535 1.3923  1  0
14: 1.1475 1.1447  0  1
15: 1.1790 1.1748  1  0
18: 1.1557 1.1552  0  1

【问题讨论】:

  • 根据描述你不会删除第13行而是根据你做的输出图片?
  • 我使用 V2 应用相同的循环,但仅在 Volume 小于时才删除,这就是为什么第 13 行在图片中被删除的原因,因为第 13 行的体积小于第 14 行的体积。
  • @akrun 我用过df[with(df, ave(Volume, grp, FUN = max)==Volume),]df[!with(df, Volume < ave(Volume, grp, FUN = max) & V1 ==1),] 但是第9行不能删除,因为第9行和第10行的Volume是一样的
  • @akrun 我刚刚发现了这个问题,所以我在描述中添加了Update(another question):。无论如何,我想我可以使用 duplicated(df$Volume) 删除相同的 Volume 行。

标签: r data.table vectorization


【解决方案1】:

你可以使用library(data.table):

setDT(df)[, .SD[(Volume == max(Volume) & V1 == 1) | V1 != 0], by = rleid(df$V1)][]

编辑:

关于掉列问题,来自akrun的改编技巧:

setDT(df)[df[, .I[(Volume == max(Volume) & V1 == 1) | V1 == 0], rleid(V1)]$V1][]

【讨论】:

  • 假设'V1'只有1和0,你需要V1==1还是V1==0
  • 你说得对,我进行了编辑。我还注意到我用 rleid 列替换了 V1 列。不幸的是,我现在没有时间优雅地“修复”它,..
  • 我猜你可以使用行索引setDT(df)[df[, .I[Volume == max(Volume)], rleid(V1)]$V1]
  • 干得好!小评论:这也将删除 consec 的非最大值。 V1=0,匹配输出图片但不匹配描述。尽管如此,请随时将其添加到您的答案中,然后我可以删除我糟糕的尝试:)。
  • 奇怪,我得到了Null data.table (0 rows and 0 cols)setDT(df)[df[, .I[(Volume == max(Volume) & V1 == 1) | V1 == 0], rleid(V1)]$V1][] 似乎是什么问题?
【解决方案2】:

我们可以从base R使用rle

grp <- inverse.rle(within.list(rle(df$V1), values <- seq_along(values)))
df[with(df, ave(Volume, grp, FUN = max)==Volume),]
#   Volume Weight V1 V2
#1  0.5367 0.5367  0  1
#4  1.1457 1.1413  1  0
#6  0.5694 0.5633  0  1
#7  1.2368 1.2343  1  0
#8  0.9662 0.9593  0  1
#10 1.4102 1.3995  1  0
#11 1.1132 1.1069  0  1
#12 1.4535 1.3923  1  0
#14 1.1475 1.1447  0  1
#15 1.1790 1.1748  1  0
#18 1.1557 1.1552  0  1

注意:我们使用 data.frame 而不是 data.table 作为输入数据

【讨论】:

  • 很棒的工作。如果我想要最低限度,我是否只需更改为FUN = min?此外,有时音量会相同,所以我会得到 0110 或 01110 而不是 0101(取决于音量相同的行数)......等等。如何删除使所有 V1 列成为 01010101 的额外 1s。干杯
  • 有没有比在df 上使用duplicated(df$Volume) 更方便的方法?谢谢
  • @Jimmy 您能否更新您的问题。您可以将max 更改为min 用于提及的情况
  • 另外,你的方法删除了V1 == 0的一些行,你不能删除V1==0的行,只能删除V1==1
【解决方案3】:

或者,您可以尝试使用tidyverse 函数。

考虑dftest作为初始数据框,标记连续的组:

dftest$f1 <- ifelse(x <- dftest$V1 == 1, cumsum(c(head(x, 1), tail(x, -1) - head(x, -1) == 1)), NA)
dftest$f2 <- ifelse(x <- dftest$V2 == 1, cumsum(c(head(x, 1), tail(x, -1) - head(x, -1) == 1)), NA)

然后对这些组进行操作:

dftest %>% 
  group_by(f1) %>%
  filter( if_else(is.na(f1), Volume == Volume, Volume == max(Volume))) %>%
  ungroup() %>%
  group_by(f2) %>%
  filter( if_else(is.na(f2), Volume == Volume, Volume == max(Volume)))

给出:

Source: local data frame [11 x 6]
Groups: f2 [7]

   Volume Weight    V1    V2    f1    f2
    <dbl>  <dbl> <int> <int> <int> <int>
1  0.5367 0.5367     0     1    NA     1
2  1.1457 1.1413     1     0     1    NA
3  0.5694 0.5633     0     1    NA     2
4  1.2368 1.2343     1     0     2    NA
5  0.9662 0.9593     0     1    NA     3
6  1.4102 1.3995     1     0     3    NA
7  1.1132 1.1069     0     1    NA     4
8  1.4535 1.3923     1     0     4    NA
9  1.1475 1.1447     0     1    NA     5
10 1.1790 1.1748     1     0     5    NA
11 1.1557 1.1552     0     1    NA     6

【讨论】:

    猜你喜欢
    • 2022-01-20
    • 2021-06-08
    • 2022-08-09
    • 2023-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-17
    • 1970-01-01
    相关资源
    最近更新 更多