dataframe分组删除异常值,分别统计删除异常值前的个数、删除异常值后的个数:
import pandas as pd
import numpy as np
# 创建一个 DataFrame
df = pd.DataFrame({
'date': ['2023-05-10', '2023-05-11', '2023-05-12'] * 4,
'type': ['A', 'B'] * 6,
'value': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 100]
})
# 定义一个函数,用于删除每个分组中的异常值
def remove_outliers(data):
q1 = data['value'].quantile(0.25)
q3 = data['value'].quantile(0.75)
iqr = q3 - q1
lower_bound = q1 - 1.5 * iqr
upper_bound = q3 + 1.5 * iqr
return data[(data['value'] >= lower_bound) & (data['value'] <= upper_bound)]
# 按照 date 和 type 分组,并删除每个分组中的异常值
grouped_df = df.groupby(['date', 'type']).apply(remove_outliers)
# 统计每个分组的数量
count_all_df = df.groupby(['date', 'type']).size().reset_index(name='count_all')
count_clean_df = grouped_df.groupby(['date', 'type']).size().reset_index(name='count_clean')
# 输出最终结果
result_df = pd.merge(count_all_df, count_clean_df, on=['date', 'type'])
print(result_df)
报错:ValueError: 'decyear' is both an index level and a column label, which is ambiguous.
报错原因:
在创建一个含有多级索引的 DataFrame时,包含了两列名称都为 decyear 的列。然后,当访问其中一个 decyear 列,但是由于存在重名列,报错。
解决方法:在执行 groupby() 操作时传入 as_index=False 参数,以保持 date 和 type 列为普通列,而不是变成索引
grouped_df = df.groupby(['date', 'type'], as_index=False).apply(remove_outliers)
# 统计每个分组的数量
count_all_df = df.groupby(['date', 'type'], as_index=False).size().reset_index(name='count_all')
count_clean_df = grouped_df.groupby(['date', 'type']).size().reset_index(name='count_clean')
注意:由于pandas升级,取消了 name 参数,所以无法使用 reset_index(name=‘count_all’),所以如果遇到这种错误,需要修改:count_all_df = df.groupby(['date', 'type'], as_index=False).size().reset_index().rename(columns={'size':'count_all'})
完整代码:
import pandas as pd
import numpy as np
# 创建一个 DataFrame
df = pd.DataFrame({
'date': ['2023-05-10', '2023-05-11', '2023-05-12'] * 4,
'type': ['A', 'B'] * 6,
'value': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 100]
})
# 定义一个函数,用于删除每个分组中的异常值
def remove_outliers(data):
q1 = data['value'].quantile(0.25)
q3 = data['value'].quantile(0.75)
iqr = q3 - q1
lower_bound = q1 - 1.5 * iqr
upper_bound = q3 + 1.5 * iqr
return data[(data['value'] >= lower_bound) & (data['value'] <= upper_bound)]
# 按照 date 和 type 分组,并删除每个分组中的异常值
grouped_df = df.groupby(['date', 'type'], as_index=False).apply(remove_outliers)
# 统计每个分组的数量
count_all_df = df.groupby(['date', 'type'], as_index=False).size().reset_index().rename(columns={'size':'count_all'})
count_clean_df = grouped_df.groupby(['date', 'type']).size().reset_index().rename(columns={'size':'count_clean'})
# 输出最终结果
result_df = pd.merge(count_all_df, count_clean_df, on=['date', 'type'])
print(result_df)