2017-08-30 30 views
5

Trong DataFrame của tôi, tôi muốn cắt giá trị của một cột cụ thể giữa 0 và 100. Ví dụ, đưa ra như sau:Pandas có thể thực hiện các hàm min() và max() theo hàng khôn ngoan không?

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

Tôi muốn nhận được:

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

Tôi biết rằng trong Pandas hoạt động số học nhất định làm việc trên các cột. Ví dụ, tôi có thể tăng gấp đôi mỗi số trong cột b như vậy:

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

Tuy nhiên điều này không làm việc cho các chức năng tích hợp như 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(). 

Có một số cách để thực hiện những gì tôi muốn có hiệu quả?

+0

thử điều này: 'df.max (trục = 1)' – MaxU

Trả lời

5

Bạn có thể sử dụng 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

vâng, đây là nó! ;) – MaxU

+1

giải pháp rất thanh lịch! – Vaishali

2

Bạn có thể sử dụng chức năng Pandas min trên trục. Sau đó kết hợp nó với min/max

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

Ví dụ

df.max(axis=1) 

Nhưng có vẻ như bạn muốn clip các giá trị thay vì min/max.

+0

Tuy đưa ra một 1 vì đây đã trả lời câu hỏi chính xác của tôi, mặc dù bạn nói đúng - - cuối cùng tôi muốn '.clip' và không' .max' cho trường hợp sử dụng cụ thể của tôi – stevendesu

0

Một cái nhìn numpy. Không thanh lịch như clip.

Lựa chọn 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 

Lựa chọn 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 

Timing
Mã Dưới

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) 
Các vấn đề liên quan