You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R中如何按类型(day)删除data.frame中每组前10%的行并保留排序

提问内容

抱歉我来自俄罗斯,英语不好。我刚开始学习R,目前遇到一个问题,恳请大家帮忙。我有一个已按V3列升序、V4列降序排序的data.frame,数据由多个文件合并汇总得到。我需要为每个类型(day)删除/过滤掉前10%的行,同时保留原有排序。

我的数据处理代码如下:

library(gdata)
myfiles <- list.files("G:/YA_3D/119_211124", pattern = ".txt", full.names = TRUE, recursive = TRUE)
myfiles1 <- lapply(myfiles, read_csv)%>% plyr::rbind.fill(myfiles1)
write.fwf(myfiles1,file="G:/DD_1-125_cor.x",sep="	", quote=F, rownames=T)
TILER <- read.table("G:/DD_1-125_cor.x", fill = TRUE, skip = 1)
TILER$V1 <- sequence(rle(as.character(TILER$V3))$lengths)

在执行上述操作前,我的data.frame如下(已将行数缩减到8行作为示例):

V1      V2      V3      V4
1       hg      2410    96
2       hg      2410    92
3       hg      2410    91
1       hg      2411    98
2       hg      2411    95
1       hg      2501    36
2       hg      2501    30

接下来我统计了每个类型的行数,将得到的数值除以100再乘以10(尝试通过V1列结合ifelse删除所有小于新表对应值的行)

TILER1 <- TILER %>% select(V3, V4)

TILER1结构如下:

V3      V4
2410    96
2410    92
2410    91
2411    98
2411    95
2501    36
2501    30

随后我执行了如下操作:

TILER.Prod_A <- desc_statby(TILER1, measure.var = "V4", grps = "V3") %>% mutate(YYY3 = ifelse(length >2000, 1, 2)) %>% 
      filter(YYY3 == "1") %>% mutate(Proz = round(length/100)*10) %>% select(V3, length, Proz)

执行上述操作后得到的新data.frame如下(示例中的Proz为模拟值,实际场景下由于行数很多,该值大于1000):

V3      length  Proz
2410    3       0.3
2411    2       0.2
2501    2       0.2

最后我尝试在两个表之间应用ifelse语句实现匹配过滤:

TILER3 <- TILER %>% mutate(T1 = ifelse(V3 == TILER.Prod_A$V3 & V1 < TILER.Prod_A$Proz, "1", "2")) %>% filter(T1 == 2)

但ifelse没有按我的预期运行,我无法筛选T1列,因为T1的取值不正确。有没有人可以提供其他可行的实现思路?

问题解答

错误原因

你之前的逻辑不符合预期,核心是跨表直接对比V3 == TILER.Prod_A$V3时,两个向量长度不匹配,R的向量循环规则会导致匹配错乱,无法实现按V3分组对应阈值的效果。你不需要单独生成阈值表再匹配,用dplyr分组操作可以一步完成过滤:

library(dplyr)

TILER3 <- TILER %>%
  # 按V3分组计算
  group_by(V3) %>%
  # 保留你原有规则:仅分组行数>2000时计算前10%截断阈值,不足2000行的分组不删除数据
  mutate(cut_line = ifelse(n() > 2000, round(n() * 0.1), 0)) %>%
  # 过滤掉前cut_line行,保留原有排序
  filter(V1 > cut_line) %>%
  # 移除临时辅助列
  ungroup() %>%
  select(-cut_line)

可选调整

如果你不需要行数>2000的限制,所有分组都删除前10%的行,把cut_line的计算逻辑换成cut_line = ceiling(n() * 0.1)即可,ceiling函数会自动将不足1的阈值向上取整为1,避免小样本分组无法过滤的问题。

内容的提问来源于stack exchange,提问作者user16073844

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 15:45:05