我有一个更大的数据集,它的结构与这个数据框类似(包括[]):
Day Worker_ID Skills Team_members
0 1 1 [1 3] [1 3]
1 1 2 [2 5] [4 2]
2 1 3 [4 2] [3 1]
3 1 4 [3 3] [2 4]
4 2 1 [2 4] [1 3]
5 2 2 [3 5] [4 2]
6 2 3 [4 3] [3 1]
7 2 4 [2 2] [2 4]
我想把我的数据框按工作人员的团队分组,所以它看起来像这样([]是可选的):
Day Team_ID Team_Skills Team_members
0 1 1 [2.5 2.5] [1 3]
1 1 2 [2.5 4] [2 4]
2 2 1 [3 3.5] [1 3]
3 2 2 [2.5 3.5] [2 4]
我假设这个过程是这样的:
- 创建原始数据帧的.copy()
- 对team_members-column中的向量进行排序
- 小组成员列& &;日列
- 删除Worker_ID列
- 创建一个新的team_id列,以便每次引入新的team_members组合时,分配一个新的团队编号
- 计算每个团队在特定日期的技能平均值,并重新命名列
下面是代码,如果你想尝试一下:
import pandas as pd
data = {'Day': [1, 1, 1, 1, 2, 2, 2, 2],
'Worker_ID': [1, 2, 3, 4, 1, 2, 3, 4],
'Skills': ['[1 3]', '[2 5]', '[4 2]', '[3 3]', '[2 4]', '[3 5]', '[4 3]', '[2 2]'],
'Team_members': ['[1 3]', '[4 2]', '[3 1]', '[2 4]', '[1 3]', '[4 2]', '[3 1]', '[2 4]']}
df = pd.DataFrame(data)
这是一种方法。首先,将团队成员字符串转换为列表,然后"删除订单"。将它们转换为frozenset(基本上是不可变的集合)。
>>> labels = df['Team_members'].str.findall("d").map(frozenset)
>>> labels
0 (1, 3)
1 (2, 4)
2 (1, 3)
3 (2, 4)
4 (1, 3)
5 (2, 4)
6 (1, 3)
7 (2, 4)
然后将数据按天分组,然后按之前的标签分组,计算每个团队的平均技能
def skills_mean(group_skills):
# worker skills matrix
group_skills = group_skills.str.findall("d").tolist()
# compute the mean along the columns
mean_skills = np.asarray(group_skills, dtype=int).mean(0)
return str(mean_skills)
>>> res = (
df.groupby(["Day", labels], as_index=False)
.agg({"Team_members": "min",
"Skills": skills_mean})
)
>>> res
Day Team_members Skills
0 1 [1 3] [2.5 2.5]
1 1 [2 4] [2.5 4. ]
2 2 [1 3] [3. 3.5]
3 2 [2 4] [2.5 3.5]
最后,添加'Team_ID'列
>>> res['Team_ID'] = res.groupby("Team_members").ngroup().add(1)
>>> res
Day Team_members Skills Team_ID
0 1 [1 3] [2.5 2.5] 1
1 1 [2 4] [2.5 4. ] 2
2 2 [1 3] [3. 3.5] 1
3 2 [2 4] [2.5 3.5] 2
这是您的问题的一般逻辑。我不会给你确切的格式,因为我在我的手机上,但这应该给你一个很好的起点。
import numpy as np
df2 = (df.assign(TS=df['Skills'].str[1:-1].str.split())
.explode('TS')
.assign(TS=lambda d: d['TS'].astype(float))
)
group = df2['Team_members'].apply(lambda r: tuple(set(r[1:-1].split())))
(df2.groupby(['Day', np.tile([0,1], len(df)), group])['TS'].mean()
.groupby(level=['Day', 'Team_members']).apply(list)
.reset_index()
)
输出:
Day Team_members TS
0 1 (1, 3) [2.5, 2.5]
1 1 (4, 2) [2.5, 4.0]
2 2 (1, 3) [3.0, 3.5]
3 2 (4, 2) [2.5, 3.5]