如何找到最后一列的值(每行),其中一些行的值全部为 NA?

问题描述 投票:0回答:4

我遇到了与如何在 R 中找到具有值(每行)的最后一列?相同的问题,除了我有没有值的行(整行 NA)。上述帖子中提供的样本没有一整排 NA。

我想知道我应该如何修改以下内容?我不想删除所有 NA 的那些行,因为它们在以后的分析中很有用。

df %>%
  rowwise %>% 
  mutate(m = {tmp <- c_across(starts_with('m'))
               tail(na.omit(tmp), 1)}) %>%
  ungroup

提前非常感谢!

r dataframe
4个回答
3
投票

如果行中的所有元素都是空的,那么一般的解决方案是创建条件为这些行返回

NA

library(dplyr)
df %>%
  rowwise %>% 
  mutate(m = {tmp <- c_across(starts_with('m'))
               if(all(is.na(tmp))) NA_character_ else 
                   tail(na.omit(tmp), 1)}) %>%
  ungroup

-输出

# A tibble: 4 × 5
     id m_1   m_2   m_3   m    
  <dbl> <chr> <chr> <chr> <chr>
1     1 a     e     i     i    
2     2 b     <NA>  <NA>  b    
3     3 <NA>  <NA>  <NA>  <NA> 
4     4 d     h     l     l    

如果OP只想返回最后一个非NA元素,我们还可以添加一个索引

[1]
来提取,当没有元素时会自动返回
NA

df %>%
  rowwise %>% 
  mutate(m = {tmp <- c_across(starts_with('m'))
               tail(na.omit(tmp), 1)[1]}) %>%
  ungroup
# A tibble: 4 × 5
     id m_1   m_2   m_3   m    
  <dbl> <chr> <chr> <chr> <chr>
1     1 a     e     i     i    
2     2 b     <NA>  <NA>  b    
3     3 <NA>  <NA>  <NA>  <NA> 
4     4 d     h     l     l    

数据

df <- structure(list(id = c(1, 2, 3, 4), m_1 = c("a", "b", NA, "d"), 
    m_2 = c("e", NA, NA, "h"), m_3 = c("i", NA, NA, "l")), row.names = c(NA, 
-4L), class = "data.frame")

3
投票

使用@akrun 的数据(非常感谢)我们可以这样做:

'\\b[^,]+$'
是正则表达式:

\\
...意味着转义(换句话说,不匹配),这在其他语言中是
R
特殊的,它只是一种
\

\\b
...元字符是一个锚点,如
^
$
符号。它匹配的位置称为“单词边界”。这场比赛的长度为零。

[^,]+
...代表字符类,这里特别使用
^
插入符号:不是
,
的一个字符。
+
在这里表示一个或多个
,

$
...表示字符串结尾或行结尾,具体取决于多行模式。

library(dplyr)
library(tidyr)
library(stringr)

df %>% 
  mutate(across(starts_with("m"), ~case_when(!is.na(.) ~ cur_column()), .names = 'new_{col}')) %>%
  unite(New_Col, starts_with('new'), na.rm = TRUE, sep = ', ') %>% 
  mutate(New_Col = str_extract(New_Col, '\\b[^,]+$'))
  id  m_1  m_2  m_3 New_Col
1  1    a    e    i     m_3
2  2    b <NA> <NA>     m_1
3  3 <NA> <NA> <NA>    <NA>
4  4    d    h    l     m_3

2
投票
library(tidyverse)
df <- data.frame(id = c(1, 2, 3, 4), m_1 = c("a", NA, "c", "d"), m_2 = c("e", NA, "g", "h"), m_3 = c("i", NA, NA, "l"))


df %>%
  rowwise() %>%
  mutate(
    nms = list(str_subset(names(df), "^m")),
    m = c_across(starts_with("m")) %>%
      {
        ifelse(test = all(is.na(.)),
          yes = NA,
          no = nms[which(. == tail(na.omit(.), 1))]
        )
      }
  ) %>%
  select(-nms)
#> # A tibble: 4 × 5
#> # Rowwise: 
#>      id m_1   m_2   m_3   m    
#>   <dbl> <chr> <chr> <chr> <chr>
#> 1     1 a     e     i     m_3  
#> 2     2 <NA>  <NA>  <NA>  <NA> 
#> 3     3 c     g     <NA>  m_2  
#> 4     4 d     h     l     m_3




# only the value no the column name
df %>%
  rowwise() %>%
  mutate(
    m = c_across(starts_with("m")) %>%
      {
        ifelse(test = all(is.na(.)),
          yes = NA,
          no = tail(na.omit(.), 1)
        )
      }
  )
#> # A tibble: 4 × 5
#> # Rowwise: 
#>      id m_1   m_2   m_3   m    
#>   <dbl> <chr> <chr> <chr> <chr>
#> 1     1 a     e     i     i    
#> 2     2 <NA>  <NA>  <NA>  <NA> 
#> 3     3 c     g     <NA>  g    
#> 4     4 d     h     l     l

reprex 包于 2022 年 1 月 1 日创建(v2.0.1)


0
投票

不确定是否仍然有用,但也许有一个更简单的答案:

library(tidyverse)

df %>%
rowwise() %>%
mutate(m=last(na.omit(c_across(starts_with('m')))))
© www.soinside.com 2019 - 2024. All rights reserved.