R语言 查找每行的最后一个非缺失值

jslywgbw  于 2023-11-14  发布在  其他
关注(0)|答案(5)|浏览(147)

我有一个在时间点0到2测量的变量var的矩阵。像这样:

df <- data.frame(id= letters[1:5],
                 var0= c(1:3, NA, 5),
                 var1= c(11, NA, NA, 14:15),
                 var2= c(NA, NA, NA, NA, 25))
df
  id var0 var1 var2
1  a    1   11   NA
2  b    2   NA   NA
3  c    3   NA   NA
4  d   NA   14   NA
5  e    5   15   25

字符串
对于每一行,也就是每个人,我想保留最新的非缺失值。所以期望的输出是:

id var0 var1 var2 last_val
1  a    1   11   NA       11
2  b    2   NA   NA        2
3  c    3   NA   NA        3
4  d   NA   14   NA       14
5  e    5   15   25       25


如何在tidyverse软件包中做到这一点?

8gsdolmq

8gsdolmq1#

你可以使用coalesce。技巧是颠倒coalesce中变量的顺序,使其返回真实的数据中最后一个非NA值:

library(dplyr)
df |> 
  mutate(last_val = coalesce(var2, var1, var0))

#   id var0 var1 var2 last_val
# 1  a    1   11   NA       11
# 2  b    2   NA   NA        2
# 3  c    3   NA   NA        3
# 4  d   NA   14   NA       14
# 5  e    5   15   25       25

字符串
如果你想使用tidy selection,你可以先定义一个coacross函数,然后再定义rev。更多关于acrosscoalescehere的用法。

coacross <- function(...) {
  coalesce(!!!across(...))
}

df |> 
  mutate(last_val = coacross(rev(contains("var"))))

wwwo4jvm

wwwo4jvm2#

一种R碱基替代品:

> df$last_val <- apply(df, 1, \(x) tail(na.omit(x), 1))
> df
  id var0 var1 var2 last_val
1  a    1   11   NA       11
2  b    2   NA   NA        2
3  c    3   NA   NA        3
4  d   NA   14   NA       14
5  e    5   15   25       25

字符串

p5cysglq

p5cysglq3#

使用max.col进行矢量化:

df$last_val <- df[,-1][cbind(1:nrow(df[,-1]), max.col(!is.na(df[,-1]), "l"))]
df
#>   id var0 var1 var2 last_val
#> 1  a    1   11   NA       11
#> 2  b    2   NA   NA        2
#> 3  c    3   NA   NA        3
#> 4  d   NA   14   NA       14
#> 5  e    5   15   25       25

字符串

4ioopgfo

4ioopgfo4#

下面是一个单行的documentr解决方案:

library(dplyr)
mutate(df, last_val = coalesce(var2, var1, var0))

字符串
测试结果:

id var0 var1 var2 last_val
1  a    1   11   NA       11
2  b    2   NA   NA        2
3  c    3   NA   NA        3
4  d   NA   14   NA       14
5  e    5   15   25       25


由于我们几乎与@Maël同时给出了我们的第一个解决方案,这里有另一个选择:

df %>% 
    mutate(last_val = apply(.[,-1], MARGIN = 1, \(x) do.call(coalesce, as.list(x[length(x):1]))))

0x6upsns

0x6upsns5#

left_join + pivot_longer的技巧

df %>%
    left_join(
        (.) %>%
            pivot_longer(!id, values_to = "last_val") %>%
            na.omit() %>%
            slice_tail(n = 1, by = id) %>%
            select(!name)
    )

字符串

id var0 var1 var2 last_val
1  a    1   11   NA       11
2  b    2   NA   NA        2
3  c    3   NA   NA        3
4  d   NA   14   NA       14
5  e    5   15   25       25

相关问题