python - 通过比较相同行是否出现在数据框中的不同组中并分配相对值,在数据框中创建新列
问题描述
我有一个看起来像这样的 DataFrame(但是 149110 行):
df = {'group':['a','a','a','a',
'b','b','b','b','b','b','b','b','b',
'c','c','c','c','c',
'd','d','d','d','d','d','d',
'e','e','e','e',],
'date':[np.datetime64('2020-01-01'),np.datetime64('2020-01-01'),np.datetime64('2020-01-01'),np.datetime64('2020-01-01'),
np.datetime64('2019-03-12'),np.datetime64('2019-03-12'),np.datetime64('2019-03-12'),np.datetime64('2019-03-12'),
np.datetime64('2019-03-12'),np.datetime64('2019-03-12'),np.datetime64('2019-03-12'),np.datetime64('2019-03-12'),
np.datetime64('2019-03-12'),
np.datetime64('2020-01-01'),np.datetime64('2020-01-01'),np.datetime64('2020-01-01'),np.datetime64('2020-01-01'),
np.datetime64('2020-01-01'),
np.datetime64('2019-01-17'),np.datetime64('2019-01-17'),np.datetime64('2019-01-17'),np.datetime64('2019-01-17'),
np.datetime64('2019-01-17'),np.datetime64('2019-01-17'),np.datetime64('2019-01-17'),
np.datetime64('2018-12-03'),np.datetime64('2018-12-03'),np.datetime64('2018-12-03'),np.datetime64('2018-12-03')],
'id':['tom','taliha','alyssa','randyl',
'tom','taliha','edward','aaron','daniel','jean','sigmund','albus','riddle',
'fellicia','ron','fred','george','alex',
'taliha','alyssa','locke','jon','jamie','sam','sydney',
'jon','jamie','sam','arya'],
'value':[1,2,3,4,
7,6,4,8,2,3,5,9,1,
1,2,3,4,5,
5,7,6,3,4,1,2,
3,2,1,4]}
df= pd.DataFrame(df)
df
group date id value
0 a 2020-01-01 tom 1
1 a 2020-01-01 taliha 2
2 a 2020-01-01 alyssa 3
3 a 2020-01-01 randyl 4
4 b 2019-03-12 tom 7
5 b 2019-03-12 taliha 6
6 b 2019-03-12 edward 4
7 b 2019-03-12 aaron 8
8 b 2019-03-12 daniel 2
9 b 2019-03-12 jean 3
10 b 2019-03-12 sigmund 5
11 b 2019-03-12 albus 9
12 b 2019-03-12 riddle 1
13 c 2020-01-01 fellicia1
14 c 2020-01-01 ron 2
15 c 2020-01-01 fred 3
16 c 2020-01-01 george 4
17 c 2020-01-01 alex 5
18 d 2019-01-17 taliha 5
19 d 2019-01-17 alyssa 7
20 d 2019-01-17 locke 6
21 d 2019-01-17 jon 3
22 d 2019-01-17 jamie 4
23 d 2019-01-17 sam 1
24 d 2019-01-17 sydney 2
25 e 2018-12-03 jon 3
26 e 2018-12-03 jamie 2
27 e 2018-12-03 sam 1
28 e 2018-12-03 arya 4
我需要一个列:together
如果该人与当前组中的另一个人在一个组中但在过去一年中,则返回 1。
例如,在“a”组中,我们有 4 个人,但 tom 和 taliha 都在一个组中,np.datetime64('2016-03-12')
即他们都在“b”组中。我们还可以看到,在“c”组中,taliha 和 alyssa 也在一起。因此,我希望 a 组的相应值together
在 tom、taliha 和 alyssa 旁边都有一个 1,但 randyl 为 0,因为他在过去一年中没有和其他任何人一起参加过。
然后对于组“b”和“c”,因为在过去一年中没有人与其他任何人在一个组中,我希望together
每个人的值都为 0。
对于去年的“d”组,我们可以看到 jon、jamie 和 sam 在同一个组中,即他们是“e”组的一部分。所以together
'd'组中 jon、jamie 和 sam 的值应该是 1,其余人的值应该是 0。
并且由于在“e”组之前没有数据,因此应该将它们都分配为 0。
然后我想创建另一个新列:rel
基于此,取决于人们在前一个组中的价值。如果过去组中的那个人的值低于另一个人,我想rel
等于 1,如果他们的值更高,我想等于 -1。
例如,在“a”组中,rel
for tom 的值应该是 -1,因为他value
在“b”中的值比 taliha高,因此rel
for taliha 的值应该是 1,因为她在“b”中的值低于value
tom '。对于 alyssa,我希望将 的值rel
设置为 -1,因为在 d 组中,她的值value
高于 talhia。
基本上想法是value
越低越好。我正在尝试按人们的过去对他们进行排名value
。因此,对于“a”组,我需要一个基本上显示 taliha > tom 和 taliha > alyssa 的系统。但我们不知道 tom 和 alyssa 之间的关系,所以我将它们视为相同的值。我也不知道 randyl 和“a”组中的其他人之间的关系,所以我希望rel
他的值设置为 0。例如,如果我发现这样的关系:人 1 > 人 2 > 人 3 并且没有人 4 的历史记录。我想rel
反映他的关系。我希望 的值rel
看起来有点像这个人 1 = 2、人 2 = 0、人 3 = -2 和人 4 = 0。
所以我希望生成的 DataFrame 看起来像这样:
group date id value together rel
0 a 2020-01-01 tom 1 1 -1
1 a 2020-01-01 taliha 2 1 1
2 a 2020-01-01 alyssa 3 1 -1
3 a 2020-01-01 randyl 4 0 0
4 b 2019-03-12 tom 7 0 0
5 b 2019-03-12 taliha 6 0 0
6 b 2019-03-12 edward 4 0 0
7 b 2019-03-12 aaron 8 0 0
8 b 2019-03-12 daniel 2 0 0
9 b 2019-03-12 jean 3 0 0
10 b 2019-03-12 sigmund 5 0 0
11 b 2019-03-12 albus 9 0 0
12 b 2019-03-12 riddle 1 0 0
13 c 2020-01-01 fellicia1 0 0
14 c 2020-01-01 ron 2 0 0
15 c 2020-01-01 fred 3 0 0
16 c 2020-01-01 george 4 0 0
17 c 2020-01-01 alex 5 0 0
18 d 2019-01-17 taliha 5 0 0
19 d 2019-01-17 alyssa 7 0 0
20 d 2019-01-17 locke 6 0 0
21 d 2019-01-17 jon 3 1 -2
22 d 2019-01-17 jamie 4 1 0
23 d 2019-01-17 sam 1 1 2
24 d 2019-01-17 sydney 2 0 0
25 e 2018-12-03 jon 3 0 0
26 e 2018-12-03 jamie 2 0 0
27 e 2018-12-03 sam 1 0 0
28 e 2018-12-03 arya 4 0 0
解决方案
我会试一试。第一个任务似乎很简单,第二个让我很头疼。我对第二部分的结果与您的预期略有不同。也许你犯了一个错误,但很可能是由于我的误解。
from itertools import combinations
df_grps = df.groupby([df.date.dt.year, 'group']).id.apply(set)
df_vals = df.set_index([df.date.dt.year, 'group', 'id']).value
results = {}
for year in sorted(df.date.dt.year.unique())[1:]:
groups = {}
for group in df_grps.loc[year].index:
ids = df_grps.loc[year, group]
together = set().union(*(
i for i in (ids & h for h in df_grps.loc[year-1]) if len(i) > 1
))
if not together:
continue
together = {i: 0 for i in together}
for i, j in combinations(together, 2):
for group_old in df_grps.loc[year-1].index:
if not {i, j} <= df_grps.at[year-1, group_old]:
continue
i_val = df_vals.at[year-1, group_old, i]
j_val = df_vals.at[year-1, group_old, j]
if i_val < j_val:
together[i] += 1
together[j] -= 1
elif i_val > j_val:
together[i] -= 1
together[j] += 1
groups[group] = together
if groups:
results[year] = groups
df_res = pd.DataFrame(
[
[year, group, i, r]
for year, groups in results.items()
for group, rel in groups.items()
for i, r in rel.items()
],
columns=['date', 'group', 'id', 'rel']
).set_index(['date', 'group', 'id'])
df.set_index([df.date.dt.year, 'group', 'id'], inplace=True)
df['together'], df['rel'] = 0, 0
df.loc[df_res.index, 'together'] = 1
df.loc[df_res.index, 'rel'] = df_res.rel
您的示例框架的结果:
date value together rel
date group id
2020 a tom 2020-01-01 1 1 -1
taliha 2020-01-01 2 1 2
alyssa 2020-01-01 3 1 -1
randyl 2020-01-01 4 0 0
2019 b tom 2019-03-12 7 0 0
taliha 2019-03-12 6 0 0
edward 2019-03-12 4 0 0
aaron 2019-03-12 8 0 0
daniel 2019-03-12 2 0 0
jean 2019-03-12 3 0 0
sigmund 2019-03-12 5 0 0
albus 2019-03-12 9 0 0
riddle 2019-03-12 1 0 0
2020 c fellicia 2020-01-01 1 0 0
ron 2020-01-01 2 0 0
fred 2020-01-01 3 0 0
george 2020-01-01 4 0 0
alex 2020-01-01 5 0 0
2019 d taliha 2019-01-17 5 0 0
alyssa 2019-01-17 7 0 0
locke 2019-01-17 6 0 0
jon 2019-01-17 3 1 -2
jamie 2019-01-17 4 1 0
sam 2019-01-17 1 1 2
sydney 2019-01-17 2 0 0
2018 e jon 2018-12-03 3 0 0
jamie 2018-12-03 2 0 0
sam 2018-12-03 1 0 0
arya 2018-12-03 4 0 0
PS:我还有一个版本更多地保留在 Pandas 框架内,但它更长。如果您有兴趣,我会发布它。
推荐阅读
- php - 在 php mysql 中显示数组
- php - PHP 警告:mysqli_real_escape_string() 期望参数 1 为 mysqli,在
- r - 如何将特定的标记点添加到 ggtern 图中?
- cumulocity - 如何在自定义 Cumulocity 应用程序中应用“开箱即用”的 Cumulocity 小部件(例如“径向计”)
- sql - 如何为包含相同值的行分配 1 个唯一编号
- sql - 使用计数案例
- django - django如何注释选择查询值中的计数
- unity3d - 全局使用统一动画
- c# - C# 解决方案中的 App.Config
- php - CURL 不适用于 MyBB 和 Flask