我最近开始尝试在tidyverse中完成所有代码。这有时使我陷入困境。这是我在tidyverse中无法完成的简单任务:我需要一个数据框中的列,该列从左返回第一个非na值的位置索引。有谁知道如何使用mutate在dplyr中实现这一目标?
这是所需的输出。
data.frame(
"X1"=c(100,rep(NA,8)),
"X2"=c(NA,10,rep(NA,7)),
"X3"=c(NA,NA,1000,1000,rep(NA,5)),
"X4"=c(rep(NA,4),25,50,10,40,50),
"FirstNonNaPosition"=c(1,2,3,3,4,4,4,4,4)
)
答案 0 :(得分:4)
将base R
元素替换为0后,max.col
是一个更简单,有效的NA
选项
max.col(replace(df2[1:4], is.na(df2[1:4]), 0), 'first')
甚至
df2$FirstNonNaPosition <- max.col(!is.na(df2[1:4]), "first")
df2$FirstNonNaPosition
#[1] 1 2 3 3 4 4 4 4 4
对于tidyverse
,可能的选项是pmap
df2 %>%
mutate(FirstNonNaPosition = pmap_int(.[-5], ~
which.max(!is.na(c(...)))))
或包装max.col
df2 %>%
mutate(FirstNonNaPosition = max.col(!is.na(.[-5]), 'first'))
df2 <- structure(list(X1 = c(100, NA, NA, NA, NA, NA, NA, NA, NA), X2 = c(NA,
10, NA, NA, NA, NA, NA, NA, NA), X3 = c(NA, NA, 1000, 1000, NA,
NA, NA, NA, NA), X4 = c(NA, NA, NA, NA, 25, 50, 10, 40, 50),
FirstNonNaPosition = c(1, 2, 3, 3, 4, 4, 4, 4, 4)),
class = "data.frame", row.names = c(NA,
-9L))
答案 1 :(得分:4)
还有base R
的可能性:
apply(df, 1, which.max)
[1] 1 2 3 3 4 4 4 4 4
与dplyr
相同:
df %>%
mutate(FirstNonNaPosition = apply(., 1, which.max))
对@Andrew提到的方案的修改:
apply(df, 1, function(x) which.max(!is.na(x)))
与dplyr
相同:
df %>%
mutate(FirstNonNaPosition = apply(., 1, function(x) which.max(!is.na(x))))
答案 2 :(得分:3)
您也可以使用apply
:
data.frame(
"X1"=c(100,rep(NA,8)),
"X2"=c(NA,10,rep(NA,7)),
"X3"=c(NA,NA,1000,1000,rep(NA,5)),
"X4"=c(rep(NA,4),25,50,10,40,50),
"FirstNonNaPosition"=c(1,2,3,3,4,4,4,4,4)
) %>%
mutate(First_Non_NA_Pos = apply(., 1, function(x) which(!is.na(x))[1]))
X1 X2 X3 X4 FirstNonNaPosition First_Non_NA_Pos
1 100 NA NA NA 1 1
2 NA 10 NA NA 2 2
3 NA NA 1000 NA 3 3
4 NA NA 1000 NA 3 3
5 NA NA NA 25 4 4
6 NA NA NA 50 4 4
7 NA NA NA 10 4 4
8 NA NA NA 40 4 4
9 NA NA NA 50 4 4