gpt4 book ai didi

R - 从数据框中删除在数字列中仅包含零的行、基本 R 和管道友好方法?

转载 作者:行者123 更新时间:2023-12-03 23:11:20 25 4
gpt4 key购买 nike

我想删除总和为 0 的所有行,但前 2 列中有因子列。我想出了一个 dplyr 解决方案,创建一个中间 rowsum 列,过滤掉总和为 0 的行,然后删除该 rowsum 列。
我想找到一种方法来使其工作而无需创建不必要的 rowsum 列,两者都使用基本 R 和 dplyr/tidyverse 管道友好方法。肯定有一段简单的单行代码可以实现这一点吗?

library(tidyverse)

df <- data.frame(person = rep(c("Ed", "Sue"), 6),
id = paste0("plot",1:12),
a = c(2, 0, 0, 0, 0, 1, 0, 0, 4, 0, 0, 0),
b = c(0, 0, 6, 4, 0, 8, 1, 0, 0, 0, 1, 1),
c = c(4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 8),
d = c(0, 0, 0, 3, 0, 1, 0, 0, 9, 0, 1, 5),
e = c(7, 0, 5, 0, 0, 1, 0, 0, 0, 0, 7, 0))


##create intermediate 'row.sum' column, filter rows that have all 0's, then remove row.sum column
df1 <- df %>%
dplyr::mutate(row.sum = a+b+c+d+e) %>%
dplyr::filter(row.sum != 0) %>%
dplyr::select(-row.sum)


#end result:
# person id a b c d e
#1 Ed plot1 2 0 4 0 7
#2 Ed plot3 0 6 0 0 5
#3 Sue plot4 0 4 0 3 0
#4 Sue plot6 1 8 0 1 1
#5 Ed plot7 0 1 0 0 0
#6 Ed plot9 4 0 0 9 0
#7 Ed plot11 0 1 3 1 7
#8 Sue plot12 0 1 8 5 0

最佳答案

dplyr 方法
您只能将 rowSums 应用于数字列,使用 dplyrs filter()across() ,与 helper where(is.numeric) :

library(dplyr)

df%>%filter(rowSums(across(where(is.numeric)))!=0)

person id a b c d e
1 Ed plot1 2 0 4 0 7
2 Ed plot3 0 6 0 0 5
3 Sue plot4 0 4 0 3 0
4 Sue plot6 1 8 0 1 1
5 Ed plot7 0 1 0 0 0
6 Ed plot9 4 0 0 9 0
7 Ed plot11 0 1 3 1 7
8 Sue plot12 0 1 8 5 0
如果您的数字列也有负值,则此方法(以及一些依赖于 rowSums() 的方法)可能会失败。
在这种情况下,我们必须确保只保留至少包含 any() 的行。非零值。这可以通过修改 rowSums() 来完成。包含条件 .x!=0across() :
df%>%filter(rowSums(across(where(is.numeric), ~.x!=0))>0)
或者使用逻辑运算符和 Reduce()/reduce() ,使用以下代码:
library(dplyr)
library(purrr)

df%>%filter(pmap_lgl(select(., where(is.numeric)), ~any(c(...)!=0)))

#or with purrr:reduce()#

df%>%filter(across(where(is.numeric), ~.x!=0)%>%reduce(`|`))
#or simply
df%>%filter(reduce(across(where(is.numeric), ~.x!=0), `|`))
基本 R 方法
您可以通过 [ 使用基本子集, 与 sapply(f, is.numeric)创建逻辑索引以仅选择数字列以提供给不等式运算符 != ,然后取 rowSums()创建的最终逻辑矩阵的结果并仅选择 rowSums > 0 的行:
df[rowSums(df[,sapply(df, is.numeric)]!=0)>0,]
编辑
我们可以从对数字向量调用逻辑函数的强制转换中受益。 as.logical()会将零评估为 FALSE,将任何非零数字评估为 TRUE。 x|x和嵌套的爆炸标志 !(!)也会这样做。这与将元素与零进行比较的其他解决方案一致,因此比 rowSums 更一致。解决方案。
一个例子:
vector<-c(0,1,2,-1)
identical(as.logical(vector), vector|vector, vector!=0, !(!vector))

[1] TRUE

考虑到这一点,有一些巧妙的方法可以解决这个问题:
df%>%filter(reduce(across(where(is.numeric), as.logical), `|`))
#or simply
df%>%filter(reduce(across(where(is.numeric)), `|`))
#and with base R:
df[Reduce(`|`, df[sapply(df, is.numeric)]),]
迄今为止最干净的,带有新的 if_any() :
df%>%filter(if_any(where(is.numeric)))

关于R - 从数据框中删除在数字列中仅包含零的行、基本 R 和管道友好方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67754119/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com