Python 将SQL结果从自联接转换为数据帧
这是一个tl;博士版本的我所追求的;详情如下: SQL查询为我提供了一个表,其中包含字段[person 1 id]、[person 2 id]和[他们在一个组中的次数]。我想转换成一个正方形的pandas数据帧——每人一行,每人一列,每个元素的值是它们在一个组中的次数。我正在寻找一种更优雅的方法来实现这一点,而不是遍历结果行,一次只填充一个元素 我有一个数据库,其中有一个任务表,其中有一列用于person_id,一列用于assignment_id。它还有其他内容,但就我们这里的目的而言,这是最重要的:Python 将SQL结果从自联接转换为数据帧,python,postgresql,pandas,Python,Postgresql,Pandas,这是一个tl;博士版本的我所追求的;详情如下: SQL查询为我提供了一个表,其中包含字段[person 1 id]、[person 2 id]和[他们在一个组中的次数]。我想转换成一个正方形的pandas数据帧——每人一行,每人一列,每个元素的值是它们在一个组中的次数。我正在寻找一种更优雅的方法来实现这一点,而不是遍历结果行,一次只填充一个元素 我有一个数据库,其中有一个任务表,其中有一列用于person_id,一列用于assignment_id。它还有其他内容,但就我们这里的目的而言,这是最重
SELECT person_id, assignment_id FROM assignments;
我想看看两个人执行同一任务的频率。因此,我:
SELECT a1.person_id AS p1_id, a2.person_id AS p2_id, COUNT(*)
FROM assignments AS a1
INNER JOIN assignments AS a2 ON a1.assignment_id = a2.assignment_id AND a1.person_id < a2.person_id
GROUP BY a1.person_id, a2.person_id
输出如下:
p1_id | p2_id | count
------+-------+------
51 | 385 | 1
163 | 385 | 1
...
现在,我正在构建一个Python脚本来访问数据,并希望将其转储到一个数据帧中,其中每个人有一行,每个人有一列,单元格有他们共享一个赋值的次数。所以输出是这样的,我不关心*单元格中的内容-可以合理地为0或该人员所做的分配数-也不关心第一行和第一列的格式:
p1_id | p_51 | p_163 | p_385
-------+--------+--------+--------
51 | * | 0 | 1
163 | 0 | * | 1
385 | 1 | 1 | *
我只有大约20个人,所以一个接一个地设置值不会影响性能,但我正在努力学习当我有更大的数据集时的良好实践。这样做的正确方法是什么
我愿意修改SQL查询,如果这是处理它的最佳方式。您可以在将所需列转换为str类型后使用,并通过连接它们以及计算它们的计数进行聚合
df[['person_id', 'assignment_id']] = df[['person_id', 'assignment_id']].astype(str)
df = df.groupby(['assignment_id'], as_index=False, sort=False)['person_id'] \
.agg({'col':','.join})['col'] \
.str.split(',').apply(lambda x: sorted(x, reverse=True)) \
.apply(pd.Series).add_prefix('p_id_') \
.set_index('p_id_0', drop=False)
通过使用获取索引p_id_0的指标变量,可以进一步简化,如下所示:
df1 = pd.get_dummies(df['p_id_1']).add_prefix('p_')
print (df1)
p_163 p_385
p_id_0
51 0.0 1.0
163 0.0 0.0
385 1.0 0.0
df2 = pd.get_dummies(df['p_id_0']).add_prefix('p_')
print (df2)
p_163 p_385 p_51
p_id_0
51 0.0 0.0 1.0
163 1.0 0.0 0.0
385 0.0 1.0 0.0
然后,在将索引帧的所有值映射到0之后,连接这些单独的数据帧,然后将相同的列命名为columns分组在一起:
df_final = pd.concat([df1, df2.applymap(lambda x: 0)], axis=1).add_prefix('p_')
print (df_final.groupby(df.columns, axis=1).sum())
p_163 p_385 p_51
p_id_0
51 0.0 1.0 0.0
163 0.0 0.0 0.0
385 1.0 0.0 0.0
杰出的谢谢
df_final = pd.concat([df1, df2.applymap(lambda x: 0)], axis=1).add_prefix('p_')
print (df_final.groupby(df.columns, axis=1).sum())
p_163 p_385 p_51
p_id_0
51 0.0 1.0 0.0
163 0.0 0.0 0.0
385 1.0 0.0 0.0