R语言筛选数据框时如何保持结果与输入筛选值顺序一致
问题描述
现有如下R数据框df:
df = structure(list(filename = c("df1.txt", "df2.txt", "df3.txt", "df4.txt"), project = c("alpha", "beta", "gamma", "delta"), lat = c(55.1852777777778, 52.6252777777778, 51.446272, 50.688111), long = c(7.15138888888889, 3.96027777777778, 1.078051, -0.343189)), row.names = c(NA, 4L ), class = "data.frame")
需要按照给定的project向量筛选对应的filename,筛选向量为:
selected = c("delta", "gamma")
使用%in%逻辑判断或者dplyr::filter筛选时,返回结果保留的是原数据框的行顺序,和selected的传入顺序不一致:
fname <- (df[df$project %in% selected,])$filename fname # [1] "df3.txt" "df4.txt"
期望输出顺序和selected顺序匹配:先返回delta对应的df4.txt,再返回gamma对应的df3.txt,即预期结果为:
fname # [1] "df4.txt" "df3.txt"
解决方案
%in%和filter的默认逻辑仅做值匹配,不会调整匹配结果的顺序,要保留筛选向量的传入顺序,可使用以下方法:
基础R实现
用match()函数完成匹配,该函数会返回筛选向量中每个元素在数据框列中对应的行位置,天然保留传入顺序:
# 仅提取filename列 fname <- df$filename[match(selected, df$project)] # 筛选整行数据 df_subset <- df[match(selected, df$project), ]
运行后得到的fname结果符合预期:
fname # [1] "df4.txt" "df3.txt"
说明:如果selected中存在df$project里没有的值,match()会返回对应位置的NA,结果中会出现空行,可通过na.omit()去除。
dplyr实现
方法1:左连接匹配
将筛选向量转为与目标列同名的tibble,通过左连接完成匹配,连接结果会自动保留左表(即筛选向量)的顺序:
library(dplyr) df_subset <- tibble(project = selected) %>% left_join(df, by = "project") fname <- df_subset$filename
方法2:匹配排序
先筛选符合条件的行,再通过arrange()结合match()按照筛选向量的顺序重排,最后提取目标列:
library(dplyr) fname <- df %>% filter(project %in% selected) %>% arrange(match(project, selected)) %>% pull(filename)
内容的提问来源于stack exchange,提问作者Haribo
相关产品推荐
相关产品推荐

