使用python将2d字典写入数据框或制表符分隔文件

lea*_*ner 2 python pandas

我有一个2-d字典,格式如下:

myDict = {('a','b'):10, ('a','c'):20, ('a','d'):30, ('b','c'):40, ('b','d'):50,('c','d'):60}
Run Code Online (Sandbox Code Playgroud)

如何将其写入制表符分隔文件,以便该文件包含以下内容.填充元组(x,y)将填充两个位置:(x,y)和(y,x).(x,x)始终为0.

输出将是:

    a   b   c   d
a   0   10  20  30
b   10  0   40  50
c   20  40  0   60
d   30  50  60  0 
Run Code Online (Sandbox Code Playgroud)

PS:如果以某种方式将字典转换为数据帧(使用pandas),那么可以使用pandas函数将其轻松写入文件

Phi*_*oud 6

你可以用鲜为人知的align方法和一点unstack魔力来做到这一点:

In [122]: s = Series(myDict, index=MultiIndex.from_tuples(myDict))

In [123]: df = s.unstack()

In [124]: lhs, rhs = df.align(df.T)

In [125]: res = lhs.add(rhs, fill_value=0).fillna(0)

In [126]: res
Out[126]:
    a   b   c   d
a   0  10  20  30
b  10   0  40  50
c  20  40   0  60
d  30  50  60   0
Run Code Online (Sandbox Code Playgroud)

最后,要将其写入CSV文件,请使用以下to_csv方法:

In [128]: res.to_csv('res.csv', sep='\t')

In [129]: !cat res.csv
        a       b       c       d
a       0.0     10.0    20.0    30.0
b       10.0    0.0     40.0    50.0
c       20.0    40.0    0.0     60.0
d       30.0    50.0    60.0    0.0
Run Code Online (Sandbox Code Playgroud)

如果你想把事物保持为整数,DataFrame.astype()那么使用,就像这样:

In [137]: res.astype(int).to_csv('res.csv', sep='\t')

In [138]: !cat res.csv
        a       b       c       d
a       0       10      20      30
b       10      0       40      50
c       20      40      0       60
d       30      50      60      0
Run Code Online (Sandbox Code Playgroud)

(由于填充了nan一个帧中的索引从另一个帧中丢失的值的中间步骤,它被转换为浮动)

@Dan Allan使用的答案combine_first很好:

In [130]: df.combine_first(df.T).fillna(0)
Out[130]:
    a   b   c   d
a   0  10  20  30
b  10   0  40  50
c  20  40   0  60
d  30  50  60   0
Run Code Online (Sandbox Code Playgroud)

时序:

In [134]: timeit df.combine_first(df.T).fillna(0)
100 loops, best of 3: 2.01 ms per loop

In [135]: timeit lhs, rhs = df.align(df.T); res = lhs.add(rhs, fill_value=0).fillna(0)
1000 loops, best of 3: 1.27 ms per loop
Run Code Online (Sandbox Code Playgroud)

这些时间可能会受到建筑成本的一点污染,那么一些非常庞大的框架会让事情看起来像什么呢?

In [143]: df = DataFrame({i: randn(1e7) for i in range(1, 11)})

In [144]: df2 = DataFrame({i: randn(1e7) for i in range(10)})

In [145]: timeit lhs, rhs = df.align(df2); res = lhs.add(rhs, fill_value=0).fillna(0)
1 loops, best of 3: 4.41 s per loop

In [146]: timeit df.combine_first(df2).fillna(0)
1 loops, best of 3: 2.95 s per loop
Run Code Online (Sandbox Code Playgroud)

DataFrame.combine_first() 更大的帧更快.


Dan*_*lan 5

In [49]: data = map(list, zip(*myDict.keys())) + [myDict.values()]

In [50]: df = DataFrame(zip(*data)).set_index([0, 1])[2].unstack()

In [52]: df.combine_first(df.T).fillna(0)
Out[52]: 
    a   b   c   d
a   0  10  20  30
b  10   0  40  50
c  20  40   0  60
d  30  50  60   0
Run Code Online (Sandbox Code Playgroud)

对于后代:如果您只是在调整,请查看Phillip Cloud的答案,以获得更简洁的构建方式df.