Pandas能够执行行级的min()和max()函数吗?

14

在我的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().

有没有一种有效地实现我想要的方式?


2
尝试这个:df.max(axis=1) - MaxU - stand with Ukraine
3个回答

16
你可以使用 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

2
是的,这就是它!;) - MaxU - stand with Ukraine
1
非常优雅的解决方案! - Vaishali

14

1
尽管你是对的——最终我想要的是.clip而不是.max,但因为这回答了我的确切问题,我仍会给一个+1。 - stevendesu

1
一个 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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接