【问题标题】:Add a counter meeting specific conditions添加满足特定条件的计数器
【发布时间】:2017-05-26 05:11:43
【问题描述】:

问题陈述

鉴于下面的数据集有两列 Column1Column 2,再添加两列名为 CounterCounting time。初始化counterCounter time的条件如下:

  1. 只有当 Column1 > 1Column2 = 0 中的值时,计数器才应该递增
  2. 计数器必须在条件满足行的 2 个值后开始递增
  3. Counting time 必须包含序列发生的次数值(满足条件的数据点序列)

具有预期输出的数据框

Column1 Column2 Counter Counter_Time  
1.1254  2.784    0        0
4.678   7.985    0        0  
8.89      0      0        1
7.65      0      0        1  
3.54      0      1        1  
4.32      0      2        1  
9.83      0      3        1
3.86     4.3     0        1
5.63     9.8     0        1
4.53      0      0        2
6.83      0      0        2   
3.431     0      4        2
8.976     0      5        2
9.864     0      6        2
7.3      9.2     0        2
2.3      3.2     0        2
4.3       0      0        3
2.1       0      0        3
4.32      0      7        3  

我遇到了类似的问题,得到了关于如何增加计数器的答案,但我无法满足上述条件。请注意,计数器应该在满足条件的两行之后开始。

来自数据集的观察

  1. 第3行满足条件,counter未初始化但Counter_Time已递增
  2. Counter 已经从第 5 行开始(根据条件前 2 行的条件满足值不应该触发计数器)
  3. 第 8 行的计数器返回 0,Counter_Time 保持不变
  4. 同样,Counter 已从第 12 行开始递增,不考虑第 10 行和第 11 行。但 Counter_time 在第 10 行递增

我已经详细阐述了问题陈述,以便专家清楚地提供准确的解决方案。

【问题讨论】:

  • 这是作业题吗?很好,你仔细考虑了这个问题,但是 SO 上的人不应该为你做功课。
  • @Marius 不,这是我的 Vehicle Prognostics 项目工作的一部分,这只是一个示例数据框,但我的实际数据约为 500K 值,我知道这可以使用 for 循环来实现,但是我从一篇类似的帖子中了解到,R 中的 for 循环速度较慢。因此,我想请专家提供逻辑和优化脚本,以便我可以改进。
  • @Marius 尊敬的先生/女士,如果您认为这是一种初学者级别的问题/喜欢给孩子做作业的问题,那么这是我的亲切请求,请让我知道解决方案.我承认我是 R 编程的初学者,我从过去几天开始使用 R 进行编码,我认为向专家寻求指导并没有错。
  • 我并不是在暗示这是一个初学者级别的问题,您的问题只是措辞有点像家庭作业问题(我很高兴接受它不是)。无论您是不是初学者,寻求帮助都可以。

标签: r row counter


【解决方案1】:
# Load packages
library(tidyverse)
library(data.table)

# Create example data frame
dt <- fread("Column1 Column2
1.1254  2.784
4.678   7.985 
8.89      0
7.65      0  
3.54      0
4.32      0  
9.83      0
3.86     4.3
5.63     9.8
4.53      0
6.83      0  
3.431     0
8.976     0
9.864     0
7.3      9.2
2.3      3.2
4.3       0
2.1       0
4.32      0  ")

### Create Counter_Time
dt2 <- dt %>%
  mutate(Merge_ID = 1:n()) %>%
  mutate(Condition = ifelse(Column1 > 1 & Column2 == 0, 1, 0)) %>%
  mutate(ID = rleid(Condition)) %>%
  mutate(Counter_Time = ifelse(Condition == 0, (ID - 1)/2, ID/2))

### Create Counter
dt3 <- dt2 %>%
  group_by(Counter_Time) %>%
  slice(3:n()) %>%
  filter(Condition == 1) %>%
  ungroup() %>%
  mutate(Counter = 1:n()) %>%
  select(Merge_ID, Counter)

### Merge dt2 and dt3 together, dt4 is the final output
dt4 <- dt2 %>%
  left_join(dt3, by = "Merge_ID") %>%
  mutate(Counter = ifelse(is.na(Counter), 0, Counter)) %>%
  select(Column1, Column2, Counter, Counter_Time)

更新

以下代码是dt2 创建后的更新。这个想法是确保当没有行满足条件时,代码仍然会生成Counter全等于0的输出。

### Set the index
begin_index <- 3

### Filter the right condition
dt3 <- dt2 %>%
  group_by(Counter_Time) %>%
  slice(begin_index:n()) %>%
  filter(Condition == 1) %>%
  ungroup() 


### Check if dt3 has any rows
if (nrow(dt3) > 0){

  dt3 <- dt3 %>%
    mutate(Counter = 1:n()) %>%
    select(Merge_ID, Counter)

  ### Merge dt2 and dt3 together, dt4 is the final output
  dt4 <- dt2 %>%
    left_join(dt3, by = "Merge_ID") %>%
    mutate(Counter = ifelse(is.na(Counter), 0, Counter)) %>%
    select(Column1, Column2, Counter, Counter_Time)

### If nrow(dt3) is 0, no rows meet the condition
} else {

  ### Create Counter column from dt2
  dt4 <- dt2 %>%
    mutate(Counter = 0) %>%
    select(Column1, Column2, Counter, Counter_Time)

}

【讨论】:

  • 如果我想增加800及以上的切片值程序失败,请您解释一下原因。
  • 我要求解释的原因是,根据我的理解slice的值将给出不考虑的行数(参考:上述问题的条件2),这个值将由前面脚本中的另一个变量给出。您的解释将有助于代码的进一步开发。
  • @Tareva 我猜不是Counter_Time 中的所有组都有超过800 的记录,所以程序失败了。
  • 那么,您有什么解决方法的建议吗?因为在最终的 R 脚本中,Slice 值和数据集中的记录数都将作为变量提供,即 Counter_TimeSlice 中的组数值本质上不会是静态的。
  • @Tareva 我不清楚此时您的预期输出是什么。如果其中一个组条件小于 800,Counter 是否会成为该组的所有 0
【解决方案2】:

使用data.table 的紧凑型解决方案(使用与@ycw 相同的数据):

library(data.table)
dt[, counter := 0
   ][, counter_time := cumsum(c(0,diff(Column1 > 1 & Column2 == 0))==1)
     ][Column1 > 1 & Column2 == 0, counter := c(0,0,rep(1,(.N-2))), by = counter_time
       ][counter == 1, counter := cumsum(counter)]

给出:

> dt
    Column1 Column2 counter counter_time
 1:  1.1254   2.784       0            0
 2:  4.6780   7.985       0            0
 3:  8.8900   0.000       0            1
 4:  7.6500   0.000       0            1
 5:  3.5400   0.000       1            1
 6:  4.3200   0.000       2            1
 7:  9.8300   0.000       3            1
 8:  3.8600   4.300       0            1
 9:  5.6300   9.800       0            1
10:  4.5300   0.000       0            2
11:  6.8300   0.000       0            2
12:  3.4310   0.000       4            2
13:  8.9760   0.000       5            2
14:  9.8640   0.000       6            2
15:  7.3000   9.200       0            2
16:  2.3000   3.200       0            2
17:  4.3000   0.000       0            3
18:  2.1000   0.000       0            3
19:  4.3200   0.000       7            3

使用的数据:

library(data.table)
dt <- fread("Column1 Column2
            1.1254  2.784
            4.678   7.985
            8.89      0
            7.65      0
            3.54      0
            4.32      0
            9.83      0
            3.86     4.3
            5.63     9.8
            4.53      0
            6.83      0
            3.431     0
            8.976     0
            9.864     0
            7.3      9.2
            2.3      3.2
            4.3       0
            2.1       0
            4.32      0")

【讨论】:

    猜你喜欢
    • 2021-05-13
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 2016-05-09
    • 1970-01-01
    • 2023-03-16
    • 2019-07-15
    • 1970-01-01
    相关资源
    最近更新 更多