wake-up-neo.com

Wie gehe ich mit "Teilen durch Null" mit Pandas-Datenrahmen um, wenn Spalten bearbeitet werden?

Ich arbeite mit Hunderten von Pandas-Datenrahmen. Ein typischer Datenrahmen sieht wie folgt aus:

import pandas as pd
import numpy as np
data = 'filename.csv'
df = pd.DataFrame(data)
df 

        one       two     three  four   five
a  0.469112 -0.282863 -1.509059  bar   True
b  0.932424  1.224234  7.823421  bar  False
c -1.135632  1.212112 -0.173215  bar  False
d  0.232424  2.342112  0.982342  unbar True
e  0.119209 -1.044236 -0.861849  bar   True
f -2.104569 -0.494929  1.071804  bar  False
....

Es gibt bestimmte Operationen, bei denen ich zwischen Spaltenwerten aufteile, z. 

df['one']/df['two'] 

Es gibt jedoch Zeiten, in denen ich durch Null oder vielleicht auch durch beide dividiere 

df['one'] = 0
df['two'] = 0

Natürlich gibt dies den Fehler aus: 

ZeroDivisionError: division by zero

Ich würde es vorziehen, wenn 0/0 eigentlich "hier ist nichts" bedeutet, da dies oft bedeutet, was eine solche Null in einem Datenrahmen bedeutet.

(a) Wie würde ich das so codieren, dass "durch Null dividieren" 0 ist?

(b) Wie würde ich dies so programmieren, dass "pass" ist, wenn die Division durch Null auftritt? 

6
ShanZhengYang

Zwei zu berücksichtigende Ansätze:

Bereiten Sie Ihre Daten so vor, dass sie niemals eine Division durch Null haben, indem Sie explizit einen Wert "keine Daten" codieren und darauf testen.

Umhüllen Sie jede Division, die zu einem Fehler führen könnte, mit einem try/except-Paar, wie unter https://wiki.python.org/moin/HandlingExceptions beschrieben.

(x,y) = (5,0)
try:
  z = x/y
except ZeroDivisionError:
  print "divide by zero"

Ich mache mir Sorgen über die Situation, in der Ihre Daten eine Null enthalten, die wirklich eine Null ist (und kein fehlender Wert).

4
vielmetti

Es ist wahrscheinlich sinnvoller, ein Datenframe zu verwenden, das im Nenner tatsächlich Null hat (siehe letzte Zeile der Spalte two).

        one       two     three   four   five
a  0.469112 -0.282863 -1.509059    bar   True
b  0.932424  1.224234  7.823421    bar  False
c -1.135632  1.212112 -0.173215    bar  False
d  0.232424  2.342112  0.982342  unbar   True
e  0.119209 -1.044236 -0.861849    bar   True
f -2.104569  0.000000  1.071804    bar  False

>>> df.one / df.two
a   -1.658442
b    0.761639
c   -0.936904
d    0.099237
e   -0.114159
f        -inf  # <<< Note division by zero
dtype: float64

Wenn einer der Werte Null ist, sollten Sie inf oder -inf im Ergebnis erhalten. Eine Möglichkeit zum Konvertieren dieser Werte ist wie folgt:

df['result'] = df.one.div(df.two)

df.loc[~np.isfinite(df['result']), 'result'] = np.nan  # Or = 0 per part a) of question.
# or df.loc[np.isinf(df['result']), ...

>>> df
        one       two     three   four   five    result
a  0.469112 -0.282863 -1.509059    bar   True -1.658442
b  0.932424  1.224234  7.823421    bar  False  0.761639
c -1.135632  1.212112 -0.173215    bar  False -0.936904
d  0.232424  2.342112  0.982342  unbar   True  0.099237
e  0.119209 -1.044236 -0.861849    bar   True -0.114159
f -2.104569  0.000000  1.071804    bar  False       NaN
13
Alexander

Sie können immer eine try-Anweisung verwenden:

try:
  z = var1/var2
except ZeroDivisionError:
  print ("0") #As python-3's rule is: Parentheses

ODER...

Sie können auch tun:

if var1==0:
    if var2==0:
        print("0")
else:
    var3 = var1/var2

Hoffe das hat geholfen! Wählen Sie die von Ihnen gewünschte Wahl (sie ist sowieso gleich).

2
Christian

Versuche dies:

df['one']/(df['two'] +.000000001)
2
Merlin
df['one'].divide(df['two'])

Code:

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.Rand(5,2), columns=list('ab'))
df.loc[[1,3], 'b'] = 0
print(df)

print(df['a'].divide(df['b']))

Ergebnis:

    a           b
0   0.517925    0.305973
1   0.900899    0.000000
2   0.414219    0.781512
3   0.516072    0.000000
4   0.841636    0.166157

0    1.692717
1         inf
2    0.530023
3         inf
4    5.065297
dtype: float64
1
Kartik