熊猫 - 从数据框架创建差异矩阵

时间:2017-09-17 17:03:35

标签: python pandas

我正在尝试创建一个矩阵来显示Pandas数据框中行之间的差异。

import pandas as pd

data = {'Country':['GB','JP','US'],'Values':[20.2,-10.5,5.7]}
df = pd.DataFrame(data)

我想这样:

  Country  Values
0      GB    20.2
1      JP   -10.5
2      US     5.7

成为这样的东西(差异垂直):

  Country     GB     JP     US
0      GB    0.0  -30.7   14.5
1      JP   30.7    0.0   16.2
2      US   14.5  -16.2    0.0

这可以通过内置函数实现,还是需要构建一个循环来获得所需的输出?谢谢你的帮助!

3 个答案:

答案 0 :(得分:7)

这是numpy' broadcasting的标准用例:

df['Values'].values - df['Values'].values[:, None]
Out: 
array([[  0. , -30.7, -14.5],
       [ 30.7,   0. ,  16.2],
       [ 14.5, -16.2,   0. ]])

我们使用values属性访问底层numpy数组,[:, None]引入一个新轴,因此结果是二维的。

您可以将其与原始系列相结合:

arr = df['Values'].values - df['Values'].values[:, None]
pd.concat((df['Country'], pd.DataFrame(arr, columns=df['Country'])), axis=1)
Out: 
  Country    GB    JP    US
0      GB   0.0 -30.7 -14.5
1      JP  30.7   0.0  16.2
2      US  14.5 -16.2   0.0

由于@Divakar:

,也可以使用以下代码生成数组
arr = np.subtract.outer(*[df.Values]*2).T

我们在subtract ufunc上调用.outer,并将其应用于所有输入对。

答案 1 :(得分:2)

我尝试改进Divakar评论:

     cars GET      /transportation(.:format)                    cars#index
          POST     /transportation(.:format)                    cars#create
  new_car GET      /transportation/new(.:format)                cars#new
 edit_car GET      /transportation/:id/edit(.:format)           cars#edit
      car GET      /transportation/:id(.:format)                cars#show
          PATCH    /transportation/:id(.:format)                cars#update
          PUT      /transportation/:id(.:format)                cars#update
          DELETE   /transportation/:id(.:format)                cars#destroy

答案 2 :(得分:0)

选项1

from itertools import product
import pandas as pd
DF=pd.DataFrame(list(product(df.Country, df.Country)), columns=['l1', 'l2'])
df=df.set_index('Country')
DF['v1']=DF.l1.map(df['Values'])
DF['v2']=DF.l2.map(df['Values'])
DF['DIFF']=DF['v2']-DF['v1']
DF.pivot(index='l1', columns='l2', values='DIFF').fillna(0).rename_axis(None).rename_axis(None,1)
Out[94]: 
      GB    JP    US
GB   0.0 -30.7 -14.5
JP  30.7   0.0  16.2
US  14.5 -16.2   0.0

选项2 使用apply

A=df['Values'].apply(lambda x : df['Values']-x)
A.columns=df.Country
A['Country']=df.Country


A
Out[124]: 
Country    GB    JP    US Country
0         0.0 -30.7 -14.5      GB
1        30.7   0.0  16.2      JP
2        14.5 -16.2   0.0      US