dplyr中的mutate问题:which.max()返回整数(0)而不是NA

i5desfxk  于 2023-05-26  发布在  其他
关注(0)|答案(1)|浏览(136)

我正在创建主数据集。我需要计算一个新的变量,它返回每一行中最大值的列位置。它是真实的数据,因此在整个主数据集中存在缺失的观测。

data.frame(v1 = c(3,2,NA,6),
           v2 = c(NA,1,6,7),
           v3 = c(1,1,NA,1)) -> df1

df1

# output
#
#   v1 v2 v3
# 1  3 NA  1
# 2  2  1  1
# 3 NA  6 NA
# 4  6  7  1

我所需要的可以很容易地计算出which.maxmutate()在dplyr。

library(dplyr)
df1 %>%
  rowwise %>%
    mutate(maxCol = which.max(c_across(everything())))

# Ouput
#
# A tibble: 4 × 4
# Rowwise: 
#      v1    v2    v3 maxCol
#   <dbl> <dbl> <dbl>  <int>
# 1     3    NA     1      1
# 2     2     1     1      1
# 3    NA     6    NA      2
# 4     6     7     1      2

如果在一行中存在NA,则max简单地忽略它们。但是,如果一行具有所有NA...

data.frame(v1 = c(3,2,NA,6),
           v2 = c(NA,1,NA,7),
           v3 = c(1,1,NA,1)) -> df2

df2

# output
#
#   v1 v2 v3
# 1  3 NA  1
# 2  2  1  1
# 3 NA NA NA
# 4  6  7  1

。。。我们遇到了一个问题

df2 %>%
  rowwise %>%
    mutate(maxCol = which.max(c_across(everything())))

# Error in `mutate()`:
#   ℹ In argument: `maxCol = which.max(c_across(everything()))`.
# ℹ In row 3.
# Caused by error:
#   ! `maxCol` must be size 1, not 0.
# ℹ Did you mean: `maxCol = list(which.max(c_across(everything())))` ?
#   Run `rlang::last_trace()` to see where the error occurred.

如果我们遵循错误消息中的建议,我们可以通过将所有内容放入列表中来计算变量

df2 %>%
  rowwise %>%
    mutate(maxCol = list(which.max(c_across(everything())))) -> dfList

dfList

# output
#
# A tibble: 4 × 4
# Rowwise: 
#      v1    v2    v3 maxCol   
#   <dbl> <dbl> <dbl> <list>   
# 1     3    NA     1 <int [1]>
# 2     2     1     1 <int [1]>
# 3    NA    NA    NA <int [0]>
# 4     6     7     1 <int [1]>

然而,这会产生各种各样的其他问题。例如,如果unlist()maxCol变量,它返回3个值而不是4个。
有没有人能提出一种使用dplyr的方法,当which.max遇到一行都是NA时,它会返回NA,而不是返回integer(0)?或者在dplyr中使用另一个函数的替代方法?
我不能简单地从主数据集中删除有问题的变量的所有NA的行,因为有问题的行只是用于计算新变量的变量的所有NA,即它们对其他变量有有效的观察,这阻止了我将它们按列表删除。

cczfrluj

cczfrluj1#

我们可以使用ifelse来捕获所有带有NA的行(将这些行设置为NA,如果不是,则继续执行命令)。

library(dplyr)

df2 %>% 
  rowwise() %>% 
  mutate(which.max = ifelse(all(is.na(c_across(everything()))), NA, which.max(c_across(everything()))))

# A tibble: 4 × 4
# Rowwise: 
     v1    v2    v3 which.max
  <dbl> <dbl> <dbl>     <int>
1     3    NA     1         1
2     2     1     1         1
3    NA    NA    NA        NA
4     6     7     1         2

相关问题