Pandas可以执行行式min()和max()函数吗?

时间:2017-08-30 17:30:36

标签: python pandas dataframe

在我的DataFrame中,我希望将特定列的值剪切为0到100.例如,给定以下内容:

  a  b
0 10 90
1 20 150
2 30 -30

我想得到:

  a  b   c
0 10 90  90
1 20 150 100
2 30 -30 0

我知道在Pandas中,某些算术运算可以跨列工作。例如,我可以将b列中的每个数字加倍,如下所示:

>>>df["c"] = df["b"] * 2
>>>df
  a  b   c
0 10 90  180
1 20 150 300
2 30 -30 -60

但是,这对minmax等内置函数无效:

>>>df["c"] = min(100, max(0, df["b"]))
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

有没有办法有效地完成我想要的东西?

3 个答案:

答案 0 :(得分:7)

您可以使用Series.clip

df['c'] = df['b'].clip(0,100)
print (df)
    a    b    c
0  10   90   90
1  20  150  100
2  30  -30    0

答案 1 :(得分:3)

您可以在轴上使用Pandas min功能。然后将其与min / max

组合

https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.min.html

例如

df.max(axis=1)

但看起来你想要剪切值而不是min / max。

答案 2 :(得分:0)

numpy视图。不如clip那么优雅。

选项1

df.assign(c=np.minimum(np.maximum(df.b.values, 0), 100))

    a    b    c
0  10   90   90
1  20  150  100
2  30  -30    0

选项2

b = df.b.values
df.assign(c=np.where(b > 100, 100, np.where(b < 0, 0, b)))

    a    b    c
0  10   90   90
1  20  150  100
2  30  -30    0

<强>时序
以下代码

res.div(res.min(1), 0)

            pir1  pir2       jez1
10     30.895514   1.0  75.210427
30     28.611177   1.0  49.913498
100    20.658307   1.0  50.823106
300    19.842134   1.0  39.162901
1000   14.078159   1.0  25.148937
3000    8.767133   1.0  15.066847
10000   4.377849   1.0   8.849138
30000   2.634263   1.0   4.653956

enter image description here

res = pd.DataFrame(
    index=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
    columns=['pir1', 'pir2', 'jez1'],
    dtype=float
)

jez1 = lambda d: d.assign(c=df.b.clip(0, 1))
pir1 = lambda d: d.assign(c=np.minimum(np.maximum(d.b.values, 0), 100))
pir2 = lambda d: (lambda b: np.where(b > 100, 100, np.where(b < 0, 0, b)))(d.b.values)

for i in res.index:
    d = pd.concat([df] * i, ignore_index=True)
    for j in res.columns:
        stmt = '{}(d)'.format(j)
        setp = 'from __main__ import d, {}'.format(j)
        res.at[i, j] = timeit(stmt, setp, number=10)

res.plot(loglog=True)