为什么当一列中有多个类别时,filter()不能正常工作?

owfi6suc  于 2023-10-13  发布在  其他
关注(0)|答案(1)|浏览(113)

我有以下 Dataframe :

set.seed(3994)
val <- seq(1:60)
cat <- rep(c("A", "B", "C"), times=c(30, 20, 10))
date <- as.Date(sample(seq(as.Date('2000/01/01'), as.Date('2020/01/01'), by="day"), 60))

df <- data.frame(val, cat, date)
df <- df %>%  
  arrange(cat, val)

我想删除每个类别的顶部和底部x百分比的数据(当数据排序时)。例如,“A”、“B”和“C”类的前2%和后2%。我有以下代码:

remove_percentile_by_category <- function(data, measurement_column, category_column, date_column, percent_to_remove) {
  # Sort the data by category and measurement (assuming it's already sorted by category)
  data_sorted <- data %>%
    arrange({{category_column}}, {{measurement_column}})

  # Calculate the number of rows for each category
  summary_data <- data_sorted %>%
    group_by({{category_column}}) %>%
    summarize(n = n())
  print(n)
  # Calculate the number of rows to remove for each category
  summary_data <- summary_data %>%
    mutate(
      n_to_remove = ceiling(n * percent_to_remove / 100)
    )
  print(summary_data)
  # Remove the top and bottom rows for each category
  data_filtered <- data_sorted %>%
    group_by({{category_column}}) %>%
    filter(row_number() > summary_data$n_to_remove & row_number() <= n() - summary_data$n_to_remove) %>%
    ungroup()

  return(data_filtered %>%
           arrange({{category_column}}, {{date_column}}))
}

我知道要删除的行数的计算是正确的,但是当涉及到下面的代码行时,问题就发生了。

filter(row_number() > summary_data$n_to_remove & row_number() <= n() - summary_data$n_to_remove)

**问题:**上面的代码没有为每个类别分配正确的n_to_remove。例如,它应该删除类别A的顶部和底部2行(总共4行),而不是只从顶部和底部删除一行(总共2行)。我做错了什么?

PS:我已经问过这个问题了。为这个问题提供的解决方案是正确的,但由于我的数据结构,给了我一些奇怪的错误。我放弃了这个解决方案,也放弃了我在这个问题中提供的原始代码。我开发了这个新代码,它可以很好地处理我的数据,但它不能正确地完成预期的任务。任何帮助都非常感谢。

fwzugrvs

fwzugrvs1#

这里有一种方法可以让你的代码工作,避免创建任何额外的嵌套:

library(dplyr, warn = FALSE)
remove_percentile_by_category <- function(data,
                                          measurement_column,
                                          category_column,
                                          date_column,
                                          percent_to_remove) {
  data %>%
    arrange({{ category_column }}, {{ measurement_column }}) %>%
    add_count({{ category_column }}) %>%
    mutate(n_to_remove = ceiling(n * percent_to_remove / 100)) %>%
    filter(row_number() > n_to_remove,
      row_number() <= n() - n_to_remove,
      .by = {{ category_column }}
    ) %>%
    select(-n, -n_to_remove)
}

count(df, cat)
#>   cat  n
#> 1   A 30
#> 2   B 20
#> 3   C 10
df_filtered <- remove_percentile_by_category(df, val, cat, percent_to_remove = 10)
count(df_filtered, cat)
#>   cat  n
#> 1   A 24
#> 2   B 16
#> 3   C  8

相关问题