Pandas文档中的术语"广播"是什么意思?

Dun*_*eal 32 python numpy pandas

我正在阅读Pandas文档,"广播"一词被广泛使用,但从未真正定义或解释过.

这是什么意思?

EdC*_*ica 48

所以术语广播来自numpy,简单地说它解释了当你在n维数组(可能是面板,数据帧,系列)或标量值之间执行操作时将产生的输出规则.

使用标量值进行广播

所以最简单的情况是乘以标量值:

In [4]:
s = pd.Series(np.arange(5))
s

Out[4]:
0    0
1    1
2    2
3    3
4    4
dtype: int32

In [5]:    
s * 10

Out[5]:
0     0
1    10
2    20
3    30
4    40
dtype: int32
Run Code Online (Sandbox Code Playgroud)

我们使用数据框获得相同的预期结果:

In [6]:    
df = pd.DataFrame({'a':np.random.randn(4), 'b':np.random.randn(4)})
df

Out[6]:
          a         b
0  0.216920  0.652193
1  0.968969  0.033369
2  0.637784  0.856836
3 -2.303556  0.426238

In [7]:    
df * 10

Out[7]:
           a         b
0   2.169204  6.521925
1   9.689690  0.333695
2   6.377839  8.568362
3 -23.035557  4.262381
Run Code Online (Sandbox Code Playgroud)

因此,技术上发生的是标量值已经沿着上面的Series和DataFrame的相同维度进行了广播.

使用1-D阵列进行广播

假设我们有一个形状为4 x 3(4行x 3列)的二维数据帧,我们可以使用与行长度相同的1-D系列沿x轴执行操作:

In [8]:
df = pd.DataFrame({'a':np.random.randn(4), 'b':np.random.randn(4), 'c':np.random.randn(4)})
df

Out[8]:
          a         b         c
0  0.122073 -1.178127 -1.531254
1  0.011346 -0.747583 -1.967079
2 -0.019716 -0.235676  1.419547
3  0.215847  1.112350  0.659432

In [26]:    
df.iloc[0]

Out[26]:
a    0.122073
b   -1.178127
c   -1.531254
Name: 0, dtype: float64

In [27]:    
df + df.iloc[0]

Out[27]:
          a         b         c
0  0.244146 -2.356254 -3.062507
1  0.133419 -1.925710 -3.498333
2  0.102357 -1.413803 -0.111707
3  0.337920 -0.065777 -0.871822
Run Code Online (Sandbox Code Playgroud)

上面看起来很有趣,直到你理解发生了什么,我拿了第一行的值并将这个行添加到df中,它可以使用这张图片来源(源自scipy):

在此输入图像描述

一般规则如下:

为了进行广播,操作中两个数组的尾随轴的大小必须相同,或者其中一个必须为1.

因此,如果我尝试添加长度不匹配的一维数组,请说一个有4个元素的数组,不像numpy会提升一个ValueError,在Pandas中你会得到一个充满NaN值的df :

In [30]:
df + pd.Series(np.arange(4))

Out[30]:
    a   b   c   0   1   2   3
0 NaN NaN NaN NaN NaN NaN NaN
1 NaN NaN NaN NaN NaN NaN NaN
2 NaN NaN NaN NaN NaN NaN NaN
3 NaN NaN NaN NaN NaN NaN NaN
Run Code Online (Sandbox Code Playgroud)

现在关于pandas的一些好处是,它将尝试使用现有的列名和行标签进行对齐,这可能会妨碍尝试执行这样的发烧友广播:

在此输入图像描述

In [55]:
df[['a']] + df.iloc[0]

Out[55]:
          a   b   c
0  0.244146 NaN NaN
1  0.133419 NaN NaN
2  0.102357 NaN NaN
3  0.337920 NaN NaN
Run Code Online (Sandbox Code Playgroud)

在上面我使用双下标强制形状为(4,1)但我们在尝试使用第一行广播时看到一个问题,因为列对齐仅在第一列上对齐.为了像上面的图表那样发生相同形式的广播,我们必须分解为numpy数组,然后成为匿名数据:

In [56]:
df[['a']].values + df.iloc[0].values

Out[56]:
array([[ 0.24414608, -1.05605392, -1.4091805 ],
       [ 0.13341899, -1.166781  , -1.51990758],
       [ 0.10235701, -1.19784299, -1.55096957],
       [ 0.33792013, -0.96227987, -1.31540645]])
Run Code Online (Sandbox Code Playgroud)

它也可能以三维方式进行广播,但我不会经常接近那些东西,但是numpy,scipy和pandas的书中有一些例子可以说明它是如何工作的.

一般来说,要记住的是,除了简单的标量值之外,对于nD数组,次/拖轴长度必须匹配,或者其中一个必须为1.

更新

似乎上面现在导致ValueError: Unable to coerce to Series, length must be 1: given 3了最新版本的熊猫0.20.2

所以你要拨打.valuesdf第一:

In[42]:
df[['a']].values + df.iloc[0].values

Out[42]: 
array([[ 0.244146, -1.056054, -1.409181],
       [ 0.133419, -1.166781, -1.519908],
       [ 0.102357, -1.197843, -1.55097 ],
       [ 0.33792 , -0.96228 , -1.315407]])
Run Code Online (Sandbox Code Playgroud)

要将其恢复到原始df,我们可以从np数组构造一个df,并将args中的原始列传递给构造函数:

In[43]:
pd.DataFrame(df[['a']].values + df.iloc[0].values, columns=df.columns)

Out[43]: 
          a         b         c
0  0.244146 -1.056054 -1.409181
1  0.133419 -1.166781 -1.519908
2  0.102357 -1.197843 -1.550970
3  0.337920 -0.962280 -1.315407
Run Code Online (Sandbox Code Playgroud)