获取R中具有相同数字的范围的最后一个条目,并进行矢量化



我有这个数据:

tribble(
~ranges, ~last,
0,     NA,
1,     NA,
1,     NA,
1,     NA,
1,     NA,
2,     NA,
2,     NA,
2,     NA,
3,     NA,
3,     NA
)

并且我希望仅在编号的最后一个条目处的行索引处用CCD_ 2列填充CCD_。这意味着,它应该是这样的:

tribble(
~ranges, ~last,
0,     0,
1,     NA,
1,     NA,
1,     NA,
1,     1,
2,     NA,
2,     NA,
2,     2,
3,     NA,
3,     3
)

到目前为止,我想出了一个按行排列的方法:

for (r in seq.int(max(tmp$ranges))) {
print(r)
range <- which(tmp$ranges == r) |> max()
tmp$last[range] <- r
}

主要问题是速度非常慢。我正在寻找一种矢量化的方法来解决这个问题。有什么创造性的解决方案吗?

这里有一个dplyr解决方案:

library(dplyr)
tmp %>%
group_by(ranges) %>%
mutate(
last = case_when(row_number() == n() ~ ranges, TRUE ~ NA_real_)
) %>%
ungroup()
# # A tibble: 10 × 2
#    ranges  last
#     <dbl> <dbl>
#  1      0     0
#  2      1    NA
#  3      1    NA
#  4      1    NA
#  5      1     1
#  6      2    NA
#  7      2    NA
#  8      2     2
#  9      3    NA
# 10      3     3

或者我们可以用基数R做一些聪明的事情来得到同样的结果。在这里,我们计算ranges的差,以确定下一行何时不同(即,组的最后一行(。然后我们在末尾粘贴一个TRUE,这样就包括了最后一行。这假设您的数据已经按ranges排序。

tmp$last = ifelse(c(diff(tmp$ranges) != 0, TRUE), tmp$ranges, NA)

使用replace:

library(dplyr)
df %>% 
group_by(ranges) %>% 
mutate(last = replace(last, n(), ranges[n()]))

使用ifelse:

library(dplyr)
df %>% 
group_by(ranges) %>% 
mutate(last = ifelse(row_number() == n(), ranges, NA)) 

使用tail:

library(dplyr)
df %>% 
group_by(ranges) %>% 
mutate(last = c(last[-n()], tail(ranges, 1)))

输出

ranges  last
<dbl> <dbl>
1      0     0
2      1    NA
3      1    NA
4      1    NA
5      1     1
6      2    NA
7      2    NA
8      2     2
9      3    NA
10      3     3