我有一个pd.Dataframe
,其中的列包含一个值,例如
df.iloc[:10]['occ']
Out[18]:
0 4220
1 205
2 7630
3 8965
4 430
5 3930
6 4230
7 5620
8 4040
9 4130
然后,我为另外的组创建了另一个包含start
和end
值的数据框。我想根据occ
值将组分配到第一个数据框。
start end
group
10 10 950
11 1000 3540
12 3600 3655
13 3700 3955
14 4000 4160
由于这些组不相交,我们有一个简单的双射。我计划为每个occ
值,取最后一行的group-index小于上述occ
值。
testAgainst = np.repeat(dfGroups['start'].values[np.newaxis, :], repeats=10, axis=0)
array([[ 10, 1000, 3600, 3700, 4000, 4200, 4300, 4700, 5000, 6000, 6200,
7000, 7700, 9000],
[ 10, 1000, 3600, 3700, 4000, 4200, 4300, 4700, 5000, 6000, 6200,
7000, 7700, 9000],
[ 10, 1000, 3600, 3700, 4000, 4200, 4300, 4700, 5000, 6000, 6200,
7000, 7700, 9000],
[ 10, 1000, 3600, 3700, 4000, 4200, 4300, 4700, 5000, 6000, 6200,
7000, 7700, 9000],
[ 10, 1000, 3600, 3700, 4000, 4200, 4300, 4700, 5000, 6000, 6200,
7000, 7700, 9000],
[ 10, 1000, 3600, 3700, 4000, 4200, 4300, 4700, 5000, 6000, 6200,
7000, 7700, 9000],
[ 10, 1000, 3600, 3700, 4000, 4200, 4300, 4700, 5000, 6000, 6200,
7000, 7700, 9000],
[ 10, 1000, 3600, 3700, 4000, 4200, 4300, 4700, 5000, 6000, 6200,
7000, 7700, 9000],
[ 10, 1000, 3600, 3700, 4000, 4200, 4300, 4700, 5000, 6000, 6200,
7000, 7700, 9000],
[ 10, 1000, 3600, 3700, 4000, 4200, 4300, 4700, 5000, 6000, 6200,
7000, 7700, 9000]])
现在,由于尺寸为(10,)
和(10, 14)
,因此应该会发生自动广播。我期待能够做到
df.iloc[:10]['occ'] < testAgainst
得到结果
0 False False False False False False True True True True True True True True
1 False True True True True True True True True True True True True True
表示前两行,因为4220
大于4200
(以及之后的所有数字),205
大于10
。
然而,我得到了
Traceback (most recent call last):
File "/home/foo/.conda/envs/myenv3/lib/python3.5/site-packages/IPython/core/interactiveshell.py", line 2881, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-28-1bce7761846c>", line 1, in <module>
df.iloc[:10]['occ'] < testAgainst
File "/home/foo/.conda/envs/myenv3/lib/python3.5/site-packages/pandas/core/ops.py", line 832, in wrapper
return self._constructor(na_op(self.values, np.asarray(other)),
File "/home/foo/.conda/envs/myenv3/lib/python3.5/site-packages/pandas/core/ops.py", line 792, in na_op
result = getattr(x, name)(y)
ValueError: operands could not be broadcast together with shapes (10,) (10,14)
df
中的2500万行)。答案 0 :(得分:1)
1)广播失败的原因是因为Series
个对象构成了一维标记的数组 [shape = (10,)
] ,与2进行比较-D array [shape = (1, 14)
] 。
让我们考虑一下:ser = df.iloc[:10]['occ']
如果你做了:
>>> ser.iloc[0] < testAgainst
array([[False, False, False, False, False, False, True, True, True,
True, True, True, True, True]], dtype=bool)
这意味着如果您可以将相同的比较应用于系列的所有行,它将为您提供正确的结果。
>>> ser.apply(lambda x: x < testAgainst.ravel())
但是,由于它没有被矢量化,因此它非常慢,因此将其应用于更多行是不可行的。
你现在可以做的是重新塑造系列,以便在其中插入额外的尺寸。
这允许NumPy分别匹配系列(10, 1)
和数组(1, 14)
的两个形状,以便可以通过各个维度的配对进行比较。
2)更优化的解决方案可能是:
>>> pd.Series((ser.values[:, None] < testAgainst).tolist()) # same as ser.values.reshape(-1,1)
结果输出:
0 [False, False, False, False, False, False, Tru...
1 [False, True, True, True, True, True, True, Tr...
2 [False, False, False, False, False, False, Fal...
3 [False, False, False, False, False, False, Fal...
4 [False, True, True, True, True, True, True, Tr...
5 [False, False, False, False, True, True, True,...
6 [False, False, False, False, False, False, Tru...
7 [False, False, False, False, False, False, Fal...
8 [False, False, False, False, False, True, True...
9 [False, False, False, False, False, True, True...
dtype: object
注意: 只需测试数组的一个样本即可,您无需重复此数组以匹配系列对象的形状。