Pandas 针对沿一个轴的系列的逐元素最小最大值
Pandas element-wise min max against a series along one axis
我有一个数据框:
df =
A B C D
DATA_DATE
20170103 5.0 3.0 NaN NaN
20170104 NaN NaN NaN 1.0
20170105 1.0 NaN 2.0 3.0
我有一个系列
s =
DATA_DATE
20170103 4.0
20170104 0.0
20170105 2.2
我想要 运行 一个元素方面的 max()
函数并沿 df
的列对齐 s
。换句话说,我想得到
result =
A B C D
DATA_DATE
20170103 5.0 4.0 NaN NaN
20170104 NaN NaN NaN 1.0
20170105 2.2 NaN 2.2 3.0
最好的方法是什么?我检查了 and series to series comparison 但没有找到针对系列的 运行 数据框的有效方法。
奖励:不确定上面的答案是否不言自明,但是如果我想将 s
沿着 行 对齐,该怎么做=16=](假设尺寸匹配)?
这称为广播,可以按如下方式完成:
import numpy as np
np.maximum(df, s[:, None])
Out:
A B C D
DATA_DATE
20170103 5.0 4.0 NaN NaN
20170104 NaN NaN NaN 1.0
20170105 2.2 NaN 2.2 3.0
此处,s[:, None]
将向 s
添加一个新轴。同样可以通过s[:, np.newaxis]
来实现。当你这样做时,它们可以一起广播,因为形状 (3, 4)
和 (3, 1)
有一个共同的元素。
注意s
和s[:, None]
的区别:
s.values
Out: array([ 4. , 0. , 2.2])
s[:, None]
Out:
array([[ 4. ],
[ 0. ],
[ 2.2]])
s.shape
Out: (3,)
s[:, None].shape
Out: (3, 1)
另一种选择是:
df.mask(df.le(s, axis=0), s, axis=0)
Out:
A B C D
DATA_DATE
20170103 5.0 4.0 NaN NaN
20170104 NaN NaN NaN 1.0
20170105 2.2 NaN 2.2 3.0
内容如下:比较 df 和 s。 df较大的地方用df,否则用s。
数据:
In [135]: df
Out[135]:
A B C D
DATA_DATE
20170103 5.0 3.0 NaN NaN
20170104 NaN NaN NaN 1.0
20170105 1.0 NaN 2.0 3.0
In [136]: s
Out[136]:
20170103 4.0
20170104 0.0
20170105 2.2
Name: DATA_DATE, dtype: float64
解决方案:
In [66]: df.clip_lower(s, axis=0)
C:\Users\Max\Anaconda4\lib\site-packages\pandas\core\ops.py:1247: RuntimeWarning: invalid value encountered in greater_equal
result = op(x, y)
Out[66]:
A B C D
DATA_DATE
20170103 5.0 4.0 NaN NaN
20170104 NaN NaN NaN 1.0
20170105 2.2 NaN 2.2 3.0
我们可以使用以下 hack 来摆脱 RuntimeWarning
:
In [134]: df.fillna(np.inf).clip_lower(s, axis=0).replace(np.inf, np.nan)
Out[134]:
A B C D
DATA_DATE
20170103 5.0 4.0 NaN NaN
20170104 NaN NaN NaN 1.0
20170105 2.2 NaN 2.2 3.0
虽然您的问题可能有更好的解决方案,但我相信这应该能满足您的需求:
for c in df.columns:
df[c] = pd.concat([df[c], s], axis=1).max(axis=1)
我有一个数据框:
df =
A B C D
DATA_DATE
20170103 5.0 3.0 NaN NaN
20170104 NaN NaN NaN 1.0
20170105 1.0 NaN 2.0 3.0
我有一个系列
s =
DATA_DATE
20170103 4.0
20170104 0.0
20170105 2.2
我想要 运行 一个元素方面的 max()
函数并沿 df
的列对齐 s
。换句话说,我想得到
result =
A B C D
DATA_DATE
20170103 5.0 4.0 NaN NaN
20170104 NaN NaN NaN 1.0
20170105 2.2 NaN 2.2 3.0
最好的方法是什么?我检查了
奖励:不确定上面的答案是否不言自明,但是如果我想将 s
沿着 行 对齐,该怎么做=16=](假设尺寸匹配)?
这称为广播,可以按如下方式完成:
import numpy as np
np.maximum(df, s[:, None])
Out:
A B C D
DATA_DATE
20170103 5.0 4.0 NaN NaN
20170104 NaN NaN NaN 1.0
20170105 2.2 NaN 2.2 3.0
此处,s[:, None]
将向 s
添加一个新轴。同样可以通过s[:, np.newaxis]
来实现。当你这样做时,它们可以一起广播,因为形状 (3, 4)
和 (3, 1)
有一个共同的元素。
注意s
和s[:, None]
的区别:
s.values
Out: array([ 4. , 0. , 2.2])
s[:, None]
Out:
array([[ 4. ],
[ 0. ],
[ 2.2]])
s.shape
Out: (3,)
s[:, None].shape
Out: (3, 1)
另一种选择是:
df.mask(df.le(s, axis=0), s, axis=0)
Out:
A B C D
DATA_DATE
20170103 5.0 4.0 NaN NaN
20170104 NaN NaN NaN 1.0
20170105 2.2 NaN 2.2 3.0
内容如下:比较 df 和 s。 df较大的地方用df,否则用s。
数据:
In [135]: df
Out[135]:
A B C D
DATA_DATE
20170103 5.0 3.0 NaN NaN
20170104 NaN NaN NaN 1.0
20170105 1.0 NaN 2.0 3.0
In [136]: s
Out[136]:
20170103 4.0
20170104 0.0
20170105 2.2
Name: DATA_DATE, dtype: float64
解决方案:
In [66]: df.clip_lower(s, axis=0)
C:\Users\Max\Anaconda4\lib\site-packages\pandas\core\ops.py:1247: RuntimeWarning: invalid value encountered in greater_equal
result = op(x, y)
Out[66]:
A B C D
DATA_DATE
20170103 5.0 4.0 NaN NaN
20170104 NaN NaN NaN 1.0
20170105 2.2 NaN 2.2 3.0
我们可以使用以下 hack 来摆脱 RuntimeWarning
:
In [134]: df.fillna(np.inf).clip_lower(s, axis=0).replace(np.inf, np.nan)
Out[134]:
A B C D
DATA_DATE
20170103 5.0 4.0 NaN NaN
20170104 NaN NaN NaN 1.0
20170105 2.2 NaN 2.2 3.0
虽然您的问题可能有更好的解决方案,但我相信这应该能满足您的需求:
for c in df.columns:
df[c] = pd.concat([df[c], s], axis=1).max(axis=1)