简体   繁体   English

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

[英]Pandas - Creating Difference Matrix from Data Frame

I'm trying to create a matrix to show the differences between the rows in a Pandas data frame. 我正在尝试创建一个矩阵来显示Pandas数据框中行之间的差异。

import pandas as pd

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

I would like this: 我想这个:

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

To become something like this (differences going vertically): 要成为这样的东西(差异垂直):

  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

Is this achievable with built-in function or would I need to build a loop to get the desired output? 这是通过内置函数实现的还是我需要构建一个循环来获得所需的输出? Thanks for your help! 谢谢你的帮助!

This is a standard use case for numpy's broadcasting : 这是numpy 广播的标准用例:

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

We access the underlying numpy array with the values attribute and [:, None] introduces a new axis so the result is two dimensional. 我们使用values属性访问底层numpy数组, [:, None] :, [:, None]引入一个新轴,因此结果是二维的。

You can concat this with your original Series: 您可以使用原始系列连接:

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

The array can also be generated with the following, thanks to @Divakar: 由于@Divakar,也可以使用以下代码生成数组:

arr = np.subtract.outer(*[df.Values]*2).T

Here we are calling .outer on the subtract ufunc and it applies it to all pair of its inputs. 这里我们在subtract .outer上调用.outer并将它应用于它的所有输入对。

I try improve Divakar comment: 我尝试改进Divakar评论:

a = np.column_stack([df['Country'], np.subtract.outer(*[-df.Values]*2)])

df = pd.DataFrame(a, columns=['Country'] + df['Country'].tolist())
print (df)
  Country    GB    JP    US
0      GB     0 -30.7 -14.5
1      JP  30.7     0  16.2
2      US  14.5 -16.2     0

Option 1 选项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

Option 2 using apply 选项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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM