python - 基于公共列合并 Pandas 数据框中的行,同时附加一些字段
问题描述
如果这是一个非常基本的问题,请原谅我是 Python 和 Pandas 的相对初学者。
我有一个观察和分类的 csv 文件。每个观察结果在结果中出现多次,因为使用不同的训练数据重复分类,由“split_on”列指示。我希望将同一观察的所有实例合并到一行中,同时保留不同的分类结果,并另外添加平均列。
这是原始形式中单个观察的样子:
约会时间 | 出价 | 数据1 | 数据2 | 数据3 | 分裂开 | 可能性 | 预言 |
---|---|---|---|---|---|---|---|
50:03.3 | WI172 | 123 | 456 | 789 | 组1 | 0.2 | 第一类 |
50:03.3 | WI172 | 123 | 456 | 789 | 组2 | 0.4 | 第一类 |
50:03.3 | WI172 | 123 | 456 | 789 | 组3 | 0.7 | 类2 |
50:03.3 | WI172 | 123 | 456 | 789 | 第 4 组 | 0.2 | 第一类 |
这是合并后的样子:
约会时间 | 出价 | 数据1 | 数据2 | 数据3 | group1_prob | group2_prob | group3_prob | group4_prob | group1_pred | group2_pred | group3_pred | group4_pred | 概率平均 | 预测平均值 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
50:03.3 | WI172 | 123 | 456 | 789 | 0.2 | 0.4 | 0.7 | 0.2 | 第一类 | 第一类 | 类2 | 第一类 | 0.375 | 第一类 |
有几个注意事项:
- 观察不一定有对应于所有可能组的行,因此 NaN 是预期的和适当的。
- 结果文件的大小约为 10GB,因此我将“chunksize”参数与“load_csv”一起使用,并且我必须为每个观察迭代每个块,以确保我拥有所有相关的行。
我写了以下内容来实现这一点:
import pandas as pd
group_cols = ["datetime", "bID"] #this is enough to uniquely identify a single observation
groups = set()
chunksize = 10 ** 6
#first pass over file collects a list of groups
for chunk in pd.read_csv("result.csv",
chunksize=chunksize, usecols=group_cols):
chunkGroups = chunk.groupby(group_cols)
for (groupLevels), chunkGroup in chunkGroups:
groups.add(groupLevels)
rows = []
#now pass over file for each group to collect associated rows
for group in groups:
result = []
for chunk in pd.read_csv("result.csv", chunksize=chunksize):
chunkGroups = chunk.groupby(group_cols)
if group in chunkGroups.groups.keys():
result.append(chunkGroups.get_group(group))
result_df = pd.concat(result) #This dataframe contains all rows pertaining to a single observation
result_df.set_index('split_on', inplace=True)
probs=result_df['probability']
probs.index += "_prob"
preds=result_df['prediction']
preds.index += "_pred"
new_row = pd.Series(result_df.iloc[0].drop(['probability','prediction']))
new_row = pd.concat([new_row,probs,preds])
#add a class label based on the average probability
new_row['probability-avg'] = result_df['probability'].mean()
if new_row['probability-avg'] > 0.5:
new_row['predictedAspect-avg'] = "class2"
else:
new_row['predictedAspect-avg'] = "class1"
rows.append(new_row)
print('merged row: ', new_row)
rows_df = pd.concat(rows, axis=1,sort=True).transpose()
rows_df.to_csv("mergedResults.csv", index=False)
这可行,但转换速度非常慢(每行几秒钟!),并且像这样处理我的整个文件将花费比我更多的时间。
有没有更明智的方法来实现这一目标?
解决方案
使用pivot
:
from statistics import mode
k = df.pivot(index=['datetime', 'bID', 'data1', 'data2', 'data3'], columns=[
'split_on'], values=['probability', 'prediction'])
k.columns = k.columns.map(lambda x: '_'.join(x[::-1]))
df = k.reset_index()
df['prediction_avg'] = df.filter(regex=r'.*_prediction').mode(1)
df['probability_avg'] = df.filter(regex=r'.*_probability').mean(1)
输出:
约会时间 | 出价 | 数据1 | 数据2 | 数据3 | group1_probability | group2_probability | group3_probability | group4_probability | group1_prediction | group2_prediction | group3_prediction | group4_prediction | 预测平均 | 概率平均值 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
50:03.3 | WI172 | 123 | 456 | 789 | 0.2 | 0.4 | 0.7 | 0.2 | 第一类 | 第一类 | 类2 | 第一类 | 第一类 | 0.375 |
推荐阅读
- java - 敏感数据的存储
- apache-flink - Flink 如何决定何时采取检查点?
- python - 带有过滤器的 Pandas 小计到整个组
- rest - POST 请求上传文件中 JWT 自动化阶段的 Quarkus Vertx 超时
- python - 如何在pytorch中重塑图像
- pandas - 覆盖 Pandas 数据框是 NA,基于多列
- pine-script - 如何从版本 2 转换为版本而不会在 pinescript 中出现未清除的 indentiier 错误?
- docker - 无法从 Springboot 应用程序连接 Kafka
- r - 根据条件将多列中的值替换为另一列的值
- html - 如何改变一个使用特定的数字格式?