R 分组方式,并在数据表中查找每组中第一个非零的索引

R 分组方式,并在数据表中查找每组中第一个非零的索引,r,group-by,dplyr,data.table,R,Group By,Dplyr,Data.table,我在R中有一个数据表,看起来像: city year target 1: NYC 2000 0 2: NYC 2000 1 3: NYC 2000 1 4: LA 2000 0 5: LA 2000 0 6: LA 2000 1 7: LA 2000 1 可通过以下方式创建: data = data.table(city = c("NYC", "NYC", "NYC", "LA", "LA", "

我在R中有一个数据表,看起来像:

   city year target
1:  NYC 2000      0
2:  NYC 2000      1
3:  NYC 2000      1
4:   LA 2000      0
5:   LA 2000      0
6:   LA 2000      1
7:   LA 2000      1
可通过以下方式创建:

data = data.table(city = c("NYC", "NYC", "NYC", "LA", "LA", "LA", "LA"),
                  year = c(2000, 2000, 2000, 2000, 2000, 2000, 2000),
                  target = c(0, 1, 1, 0, 0, 1, 1))
我想按
城市
年份
对它们进行分组,并在
目标
列中找到第一个非零元素的索引,以便我可以修改它,期望的结果应该如下所示:

   city year target
1:  NYC 2000      0
2:  NYC 2000    666
3:  NYC 2000      1
4:   LA 2000      0
5:   LA 2000      0
6:   LA 2000    666
7:   LA 2000      1
感谢您的帮助

以下操作不起作用:

cutoff_thresh <- function(x, cutoff) {x > cutoff}

helper <- data %>% 
          group_by(city, year) %>%
          mutate(thresh = detect_index(.x = target,
                 .f = cutoff_thresh,
                  cutoff = 0)
                 )
cutoff\u thresh cutoff}
助手%
组别(城市,年份)%>%
突变(阈值=检测指数(.x=目标,
.f=截止值\阈值,
截止值=0)
)
它产生给定年份中第一个非零元素出现的确切日期,
它从每年的第一天开始计算。因此,如果2000年有365天,而2001年的第2天我们是非零的,它返回
2
(纽约,2001)
,而不是
365+2
。毫不奇怪

由于数据集已经是一个
数据表
,因此使用
数据表
方法可能更有效。按“城市”、“年份”分组,获取第一个非零元素(“i1”)的行索引(
.I
),在
I
中使用该索引,并将(
:=
)的“目标”值分配给666

library(data.table)
i1 <- data[, .I[target != 0][1], .(city, year)]$V1
data[i1, target := 666][]
#    city year target
#1:  NYC 2000      0
#2:  NYC 2000    666
#3:  NYC 2000      1
#4:   LA 2000      0
#5:   LA 2000      0
#6:   LA 2000    666
#7:   LA 2000      1
或与
匹配

data %>% 
   group_by(city, year) %>%
   mutate(target = replace(target, match(1, target), 666))
注意:即使特定组的“目标”中没有1,所有解决方案都有效

e、 g

data$target[6:7]%
组别(城市,年份)%>%
突变(target=replace(target,其中(target!=0)[1],666))
#一个tibble:7x3
#组别:城市,年份[2]
#城市年目标
#     
#1纽约市2000 0
#2纽约市2000 666
#3纽约市2000 1
#4洛杉矶2000 0
#5洛杉矶2000 0
#6洛杉矶2000 0
#7洛杉矶2000 0

使用
dplyr
您可以使用组中的
which.max
找到第一个非零元素的索引,并将其替换为666

library(dplyr)

data %>%
  group_by(city, year) %>%
  mutate(target = replace(target, which.max(target != 0), 666))


#  city   year target
#  <chr> <dbl>  <dbl>
#1 NYC    2000      0
#2 NYC    2000    666
#3 NYC    2000      1
#4 LA     2000      0
#5 LA     2000      0
#6 LA     2000    666
#7 LA     2000      1

使用data.table,使用mult=参数连接,仅编辑符合连接条件的第一行(如果有)


很好的技巧,使用
which.max
查找第一个非零元素。另一种
data.table
方法使用
replace
类似于您的第一种方法:
data[,target:=replace(target,cumsum(target!=0)=1L,666L),by=(city,year)]
data$target[6:7] <- 0
data %>%
    group_by(city, year) %>% 
    mutate(target = replace(target, which(target != 0)[1], 666))
# A tibble: 7 x 3
# Groups:   city, year [2]
#  city   year target
#  <chr> <dbl>  <dbl>
#1 NYC    2000      0
#2 NYC    2000    666
#3 NYC    2000      1
#4 LA     2000      0
#5 LA     2000      0
#6 LA     2000      0
#7 LA     2000      0
library(dplyr)

data %>%
  group_by(city, year) %>%
  mutate(target = replace(target, which.max(target != 0), 666))


#  city   year target
#  <chr> <dbl>  <dbl>
#1 NYC    2000      0
#2 NYC    2000    666
#3 NYC    2000      1
#4 LA     2000      0
#5 LA     2000      0
#6 LA     2000    666
#7 LA     2000      1
data %>%
  group_by(city, year) %>%
  mutate(target = ifelse(row_number() == which.max(target != 0), 666, target))
> data[.(unique(city), 1), on=.(city, target), mult="first", target := 999]
> data
   city year target
1:  NYC 2000      0
2:  NYC 2000    999
3:  NYC 2000      1
4:   LA 2000      0
5:   LA 2000      0
6:   LA 2000    999
7:   LA 2000      1