2017-08-30 8 views
5

In meinem Dataframe Ich wünsche zwischen 0 und 100. Zum Beispiel mit dem folgenden dem Wert einer bestimmten Spalte befestigen:Können Pandas zeilenweise min() und max() Funktionen ausführen?

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

Ich mag bekommen:

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

Ich weiß, dass in Pandas bestimmte arithmetische Operationen arbeiten über Spalten hinweg. Zum Beispiel könnte ich jede Zahl in der Spalte b wie so verdoppeln:

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

jedoch nicht für integrierte Funktionen wie min und max funktioniert: zu erreichen

>>>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(). 

Gibt es irgendeine Art und Weise was ich will effizient?

+0

try this: 'df.max (Achse = 1)' – MaxU

Antwort

5

können Sie Series.clip verwenden:

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

ja, das ist es! ;) – MaxU

+1

sehr elegante Lösung! – Vaishali

2

Sie können die Funktion Pandas min über eine Achse verwenden. kombinieren sie dann mit min/max

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

Zum Beispiel

df.max(axis=1) 

Aber es sieht aus wie Sie die Werte statt min/max Clip wollen.

+0

Noch ein +1 geben, weil dies meine genaue Frage beantwortet, obwohl du hast Recht - - Letztendlich wollte ich '.clip' und nicht' .max' für meinen speziellen Anwendungsfall – stevendesu

0

Ein numpy Ansicht. Nicht so elegant wie clip.

Option 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 

Option 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
Code unten

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)