我有一个如下所示的数据框
我想知道是否存在一种最快的方法来在熊猫中创建一个python字典,该字典将保存如下所示的数据
table = {2: [4, 5, 6, 7, 8 ...], 4: [1, 2, 3, 4, ...]}
这里的键是用户ID,值是日期的唯一列表。
这可以在核心python的早期完成,但是想知道是否有基于pandas或numpy的方法来快速计算。我需要一个快速的解决方案,当此数据帧变大时,它可以很好地扩展。
编辑1:表演
花费的时间:每个循环14.3 ms±134 µs(平均±标准偏差,共运行7次,每个循环100个循环)
levels = pd.DataFrame({k: df.index.get_level_values(k) for k in range(2)})
table = levels.drop_duplicates()\
.groupby(0)[1].apply(list)\
.to_dict()
print(table)
花费的时间:每个循环17.4 ms±105 µs(平均±标准偏差,共运行7次,每个循环100个循环)
res.reset_index().drop_duplicates(['user_id','date']).groupby('user_id')['date'].apply(list).to_dict()
花费的时间:每循环294 ms±12.8 ms(平均±标准偏差,共运行7次,每个循环1次)
a = {k: list(pd.unique(list(zip(*g))[1]))
for k, g in groupby(df.index.values.tolist(), itemgetter(0))}
print (a)
花费的时间:每个循环15 ms±187 µs(平均±标准偏差,运行7次,每个循环100个循环)
pd.Series(res.index.get_level_values(1), index=res.index.get_level_values(0)).groupby(level=0).apply(set).to_dict()
编辑2:再次进行基准测试
错误的结果
idx = df.index.droplevel(-1).drop_duplicates()
l1, l2 = idx.levels
mapping = defaultdict(list)
for i, j in zip(l1, l2):
mapping[i].append(j)
改进的时间:每个循环14.6 ms±58.8 µs(平均±标准偏差,共运行7次,每个循环100个循环)
a = {k: list(set(list(zip(*g))[1]))
for k, g in groupby(res.index.values.tolist(), itemgetter(0))}
答案 0 :(得分:4)
来自Jz的数据
pd.Series(df.index.get_level_values(0),index=df.index.get_level_values(1)).groupby(level=0).apply(set).to_dict()
Out[92]: {4: {'a', 'b'}, 5: {'a', 'b'}}
如果仅需要列表,则可以添加apply(list)
PS:个人认为不需要此步骤
pd.Series(df.index.get_level_values(0),index=df.index.get_level_values(1)).groupby(level=0).apply(set).apply(list).to_dict()
Out[93]: {4: ['b', 'a'], 5: ['b', 'a']}
答案 1 :(得分:3)
这是使用drop_duplicates
+ groupby
的一种解决方案。
levels = pd.DataFrame({k: df.index.get_level_values(k) for k in range(2)})
table = levels.drop_duplicates()\
.groupby(0)[1].apply(list)\
.to_dict()
print(table)
{1: [2, 3], 2: [8, 9]}
设置
df = pd.DataFrame([[1, 2, 0, 3], [1, 2, 1, 4], [1, 3, 1, 5],
[2, 8, 1, 3], [2, 8, 1, 4], [2, 9, 2, 5]],
columns=['col1', 'col2', 'col3', 'col4'])
df = df.set_index(['col1', 'col2', 'col3'])
print(df)
col4
col1 col2 col3
1 2 0 3
1 4
3 1 5
2 8 1 3
1 4
9 2 5
答案 2 :(得分:2)
我认为,如果需要更好的性能,请将itertools.groupby
与unique
配合使用,以与原始数据相同的顺序返回列表。如果顺序不重要,请使用set
:
df = pd.DataFrame({'A':list('abcdef'),
'B':[4,5,4,5,5,4],
'C':[7,8,9,4,2,3],
'D':[1,3,5,7,1,0],
'E':[5,3,6,9,2,4],
'F':list('aaabbb')}).set_index(['F','B', 'A'])
print (df)
C D E
F B A
a 4 a 7 1 5
5 b 8 3 3
4 c 9 5 6
b 5 d 4 7 9
e 2 1 2
4 f 3 0 4
from itertools import groupby
from operator import itemgetter
a = {k: list(set(list(zip(*g))[1]))
for k, g in groupby(df.index.values.tolist(), itemgetter(0))}
print (a)
{'a': [4, 5], 'b': [5, 4]}
另一种熊猫解决方案:
d = df.reset_index().drop_duplicates(['F','B']).groupby('F')['B'].apply(list).to_dict()
print (d)
{'a': [4, 5], 'b': [5, 4]}