如何用dplyr按行删除data frame的NA变量并计算多样性?
按行清理NA并计算多样性值的解决方案
我来帮你搞定这个问题!你需要的是按行保留非NA的4个变量,而非删除整行数据,drop_na()和select()确实不适用这个场景。下面用dplyr结合vegan包给出两种可行的实现方式:
第一步:准备环境与数据
首先加载需要的包,并重现你的数据框:
library(dplyr) library(vegan) # 还原你的数据框 df <- structure(list(Q = c(NA, 346.86, 166.95, 162.57, NA, NA, NA, 266.7), L = c(18.93, NA, 15.72, 39.51, NA, NA, NA, NA), C = c(NA, 23.8, NA, 8.47, 20.89, 18.72, 14.94, NA), X = c(40.56, NA, 26.05, 3.08, 23.77, 59.37, NA, NA), W = c(29.47, NA, NA, NA, 36.08, NA, 27.34, 28.19), S = c(NA, 7.47, NA, NA, 18.64, NA, 25.34, NA), Y = c(NA, 2.81, 0, NA, NA, 21.18, 10.83, 12.19), H = c(0, NA, NA, NA, NA, 0, NA, 0)), class = "data.frame", row.names = c(NA, -8L))
方法一:用rowwise()按行处理
这是最直观的dplyr风格写法,通过rowwise()告诉dplyr要逐行操作:
result_df <- df %>% rowwise() %>% # 提取当前行所有列的值,去掉NA后计算多样性 mutate(diversity_val = diversity(na.omit(c_across(everything())), index = "shannon")) %>% ungroup() # 取消按行分组,恢复常规数据框操作 # 查看结果 print(result_df)
c_across(everything()):获取当前行的所有变量值,拼成一个向量na.omit():过滤掉向量中的NA值,正好剩下4个有效值diversity():传入处理后的向量计算多样性,默认是Shannon指数,可通过index参数改为simpson等其他指数
方法二:用purrr::pmap()映射处理
如果你习惯用函数式编程的风格,purrr的映射函数也能高效完成任务:
library(purrr) result_df <- df %>% mutate(diversity_val = pmap_dbl(., ~diversity(na.omit(c(...)), index = "shannon")))
pmap_dbl():逐行遍历数据框,把每行的元素作为参数传入匿名函数c(...):把当前行的所有元素拼成向量,后续步骤和方法一一致
为什么之前的方法不适用?
drop_na():作用是删除包含NA的整行,而不是保留行内的非NA元素,不符合你的需求select():用于选择或删除列,无法针对行内的元素进行过滤操作
内容的提问来源于stack exchange,提问作者Tianjian Qin




