Ответ 1
используйте np.add.outer():
In [65]: pd.DataFrame(np.add.outer(df['Size'], df['Size']),
columns=df['ID'].values,
index=df['ID'].values)
Out[65]:
a b c d e f g
a 8 7 4 6 13 9 7
b 7 6 3 5 12 8 6
c 4 3 0 2 9 5 3
d 6 5 2 4 11 7 5
e 13 12 9 11 18 14 12
f 9 8 5 7 14 10 8
g 7 6 3 5 12 8 6
UPDATE: (Pandas Multi-Index) подход (ПРИМЕЧАНИЕ: этот подход намного медленнее по сравнению с предыдущим):
In [33]: r = pd.DataFrame(np.array(list(combinations(df['Size'], 2))).sum(axis=1),
...: index=pd.MultiIndex.from_tuples(list(combinations(df['ID'], 2))),
...: columns=['TotalSize']
...: )
In [34]: r
Out[34]:
TotalSize
a b 7
c 4
d 6
e 13
f 9
g 7
b c 3
d 5
e 12
f 8
g 6
c d 2
e 9
f 5
g 3
d e 11
f 7
g 5
e f 14
g 12
f g 8
Доступ к нему можно получить следующим образом:
In [41]: r.loc[('a','b')]
Out[41]:
TotalSize 7
Name: (a, b), dtype: int32
In [42]: r.loc[('a','b'), 'TotalSize']
Out[42]: 7
In [44]: r.loc[[('a','b'), ('c','d')], 'TotalSize']
Out[44]:
a b 7
c d 2
Name: TotalSize, dtype: int32
In [43]: r.at[('a','b'), 'TotalSize']
Out[43]: 7
Сравнение использования памяти (форма DF: 7000x3
):
In [65]: df = pd.concat([df] * 1000, ignore_index=True)
In [66]: df.shape
Out[66]: (7000, 2)
In [67]: r1 = pd.DataFrame(np.add.outer(df['Size'], df['Size']),
...: columns=df['ID'].values,
...: index=df['ID'].values)
...:
In [68]: r2 = pd.DataFrame(np.array(list(combinations(df['Size'], 2))).sum(axis=1),
...: index=pd.MultiIndex.from_tuples(list(combinations(df['ID'], 2))),
...: columns=['TotalSize'])
...:
In [69]: r1.memory_usage().sum()/r2.memory_usage().sum()
Out[69]: 2.6685407829018244
Сравнение скорости (форма DF: 7000x3
):
In [70]: %%timeit
...: r1 = pd.DataFrame(np.add.outer(df['Size'], df['Size']),
...: columns=df['ID'].values,
...: index=df['ID'].values)
...:
180 ms ± 2.99 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [71]: %%timeit
...: r2 = pd.DataFrame(np.array(list(combinations(df['Size'], 2))).sum(axis=1),
...: index=pd.MultiIndex.from_tuples(list(combinations(df['ID'], 2))),
...: columns=['TotalSize'])
...:
17 s ± 325 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)