R - 基于列名(在向量中)和这些列中的特定值的子集行
R - subset rows based on column names (in a vector) and specific values in those columns
这是我的 df
的样子:
df <- data.frame(WoS = c(1L, NA, 1L, NA, 1L, NA), Scopus = c(1L, 1L, 1L, 1L, NA, NA), Dim = c(NA, NA, 1L, 1L, 1L, 1L), Lens = c(NA, NA, NA, 1L, NA, 1L))
或:
| WoS| Scopus| Dim| Lens| # (+ various other columns)
|---:|------:|---:|----:|
| 1| 1| NA| NA|
| NA| 1| NA| NA|
| 1| 1| 1| NA|
| NA| 1| 1| 1|
| 1| NA| 1| NA|
| NA| NA| 1| 1|
# (+ hundreds of other rows in which 1 and NAs are distributed among these four columns)
我想根据存储列名的向量对 df
进行子集化;这些列中至少一列的值应等于 1
.
在vec
中提到的不是的其他列应该是NA
.
示例:
假设我有一个向量 vec <- c("WoS", "Scopus")
。
然后我想 select df$WoS = 1
或 df$Scopus = 1
以及 is.na(df$Dim)
和 is.na(df$Lens)
的所有行:
| WoS| Scopus| Dim| Lens| # (+ keep all other columns ...)
|---:|------:|---:|----:|
| 1| 1| NA| NA|
| NA| 1| NA| NA|
| 1| NA| NA| NA|
| NA| 1| NA| NA|
| 1| 1| NA| NA|
如何以最佳方式做到这一点?
我们可以将列名存储到向量中,然后filter
适用于不同的条件。
library(dplyr)
target1 <- c("WoS", "Scopus")
target2 <- c("Dim", "Lens")
df2 <- df %>%
filter(rowSums(select(., all_of(target1)), na.rm = TRUE) <= 2) %>%
filter(across(all_of(target2), .fns = is.na))
df2
# WoS Scopus Dim Lens
# 1 1 1 NA NA
# 2 NA 1 NA NA
如果您不喜欢使用rowSums
,因为某些列中的值可能不是严格的1,我们可以更改为以下,使用filter
和if_any
。
df2 <- df %>%
filter(if_any(all_of(target1), .fns = function(x) x == 1)) %>%
filter(across(all_of(target2), .fns = is.na))
df2
# WoS Scopus Dim Lens
# 1 1 1 NA NA
# 2 NA 1 NA NA
我们也可以把第二个filter
函数中的across
改成if_all
.
df2 <- df %>%
filter(if_any(all_of(target1), .fns = function(x) x == 1)) %>%
filter(if_all(all_of(target2), .fns = is.na))
df2
# WoS Scopus Dim Lens
# 1 1 1 NA NA
# 2 NA 1 NA NA
这是我的 df
的样子:
df <- data.frame(WoS = c(1L, NA, 1L, NA, 1L, NA), Scopus = c(1L, 1L, 1L, 1L, NA, NA), Dim = c(NA, NA, 1L, 1L, 1L, 1L), Lens = c(NA, NA, NA, 1L, NA, 1L))
或:
| WoS| Scopus| Dim| Lens| # (+ various other columns)
|---:|------:|---:|----:|
| 1| 1| NA| NA|
| NA| 1| NA| NA|
| 1| 1| 1| NA|
| NA| 1| 1| 1|
| 1| NA| 1| NA|
| NA| NA| 1| 1|
# (+ hundreds of other rows in which 1 and NAs are distributed among these four columns)
我想根据存储列名的向量对 df
进行子集化;这些列中至少一列的值应等于 1
.
在vec
中提到的不是的其他列应该是NA
.
示例:
假设我有一个向量 vec <- c("WoS", "Scopus")
。
然后我想 select df$WoS = 1
或 df$Scopus = 1
以及 is.na(df$Dim)
和 is.na(df$Lens)
的所有行:
| WoS| Scopus| Dim| Lens| # (+ keep all other columns ...)
|---:|------:|---:|----:|
| 1| 1| NA| NA|
| NA| 1| NA| NA|
| 1| NA| NA| NA|
| NA| 1| NA| NA|
| 1| 1| NA| NA|
如何以最佳方式做到这一点?
我们可以将列名存储到向量中,然后filter
适用于不同的条件。
library(dplyr)
target1 <- c("WoS", "Scopus")
target2 <- c("Dim", "Lens")
df2 <- df %>%
filter(rowSums(select(., all_of(target1)), na.rm = TRUE) <= 2) %>%
filter(across(all_of(target2), .fns = is.na))
df2
# WoS Scopus Dim Lens
# 1 1 1 NA NA
# 2 NA 1 NA NA
如果您不喜欢使用rowSums
,因为某些列中的值可能不是严格的1,我们可以更改为以下,使用filter
和if_any
。
df2 <- df %>%
filter(if_any(all_of(target1), .fns = function(x) x == 1)) %>%
filter(across(all_of(target2), .fns = is.na))
df2
# WoS Scopus Dim Lens
# 1 1 1 NA NA
# 2 NA 1 NA NA
我们也可以把第二个filter
函数中的across
改成if_all
.
df2 <- df %>%
filter(if_any(all_of(target1), .fns = function(x) x == 1)) %>%
filter(if_all(all_of(target2), .fns = is.na))
df2
# WoS Scopus Dim Lens
# 1 1 1 NA NA
# 2 NA 1 NA NA