0

I am trying to compare values in a table, it so happens that some might be zero and I therefore get an error message that I cannot divide by 0. Why isn't the script returning inf instead of an error? When I test this script on a dataframe with one column it works, with more than one column it breaks with the Zero Division Error.

table[change] = ['{0}%'.format(str(round(100*x,2)) for x in \
                                         (table.ix[:,table.shape[1]-1] - table.ix[:,0]) / table.ix[:,0]]

table example:

         0      1      2      3      4      5      6  \
numbers  0.0  100.0  120.0  220.0  250.0  300.0  500.0\\
revenues 50.0  100.0  120.0  220.0  250.0  300.0  500.0

where table.ix[:,0] is 0.0.

Some of the values at table.ix[:,0] are zero and others are not, hence, try and except in my experience will not work because the script will break once the value divisible is equal to 0.

I tried two of the other methods and they did not work for me.

Can you be a little more descriptive in your answer? I am struggling to take the approach given.

I have another approach which I am trying and it is not working. Do not see yet what the problem is:

for index, row in table.iterrows():
    if row[0] == 0:
        table[change] = 'Nan'
    else:
        x = (row[-1] - row[0]) / row[0]
        table[change] = '{0} {1}%'.format( str(round(100 * x, 2)))

The 'change' column contains the same values (i.e. the last comparison of the table)

OAK
  • 2,994
  • 9
  • 36
  • 49

2 Answers2

1

Looks like python has a specific ZeroDivisionError, you should use try except to do something else in that case.

try:
    table[change] = ['{0}%'.format(str(round(100*x,2)) for x in \
                                         (table.ix[:,table.shape[1]-1] - table.ix[:,0]) / table.ix[:,0]]
except ZeroDivisionError:
    table[change] = inf

In that case, you can just divide the whole Series, and Pandas will do the inf substitution for you. Something like:

if df1.ndim == 1:
    table[change] = inf
elif df1.ndim > 1 and df1.shape[0] > 1:
    table[change] = ['{0}%'.format(str(round(100*x,2)) for x in \
                                             (table.ix[:,table.shape[1]-1] - table.ix[:,0]) / table.ix[:,0]]

The fact that your original example only had one row seems to make Pandas fetch the value in that cell for the division. If you do the division with an array with more than one row, it has the behaviour that I think you were originally expecting.

EDIT:

I've just spotted the generator expression that I completely overlooked. This is much easier than I thought. Performing your normalisation then, if your version of pandas is up to date, then you can call round if you want.

table["change"] = 100 * ((table.iloc[:, -1] - table.iloc[:, 0])/ table.iloc[:, 0])
#And if you're running Pandas v 0.17.0
table.round({"change" : 2})
Andrew
  • 1,072
  • 1
  • 7
  • 15
  • @AndrewL. That would insert inf (or whatever placeholder) I would define into each row in table[change]. I'll elaborate the description further above. – OAK Sep 05 '16 at 15:35
  • `NameError: name 'inf' is not defined`. Perhaps you mean `float('inf')`, and I guess you could assign `inf = float('inf')`. Note that `0/0` should probably result in NaN, _not_ inf. – PM 2Ring Sep 05 '16 at 15:36
  • @PM2Ring in the python version I'm using `inf` is already defined as a float without me having to explicitly define it. – Andrew Sep 05 '16 at 15:39
  • Interesting. That doesn't happen for me in either Python 2.6 or 3.6. What version is that? Are you perhaps importing `inf` somehow, either explicitly, or a "magic" import performed by your IDE? – PM 2Ring Sep 05 '16 at 15:48
  • Could be a magic import, hadn't really considered that possibility. I'm using 2.7.9 in Enthought's Canopy. Working in Ipython, I'm reading that it does `from numpy import inf` in the background. Good to know – Andrew Sep 05 '16 at 15:50
  • @Andrew. In this case though, a try and except approach will not work because the code will break as soon as it sees 0 at `table.ix[:,0]`. I'm looking for other rows in table[change] to have the comparison. – OAK Sep 05 '16 at 16:04
  • The `if/elif` should suffice then. As soon as you have more than one row, python starts treating it like an array, with the usual `numpy` divide by zero behaviour. – Andrew Sep 05 '16 at 18:24
  • 1
    Yes Canopy does `from numpy import *` I think. – ayhan Sep 05 '16 at 18:35
  • @Andrew. Thanks your solution works with if/elif. Oddly enough, the scrips runs smoothly in the command line or in pyCharm with Anaconda on my local machine at home. But at work I get this Zero Division Error. I am certain that the interpreter is the same, the dependencies (not 100%) and definitely the data object and structure is the same. What could cause this? Perhaps I should try a different approach? – OAK Sep 05 '16 at 19:16
1

Dividing by zero is usually a serious error; defaulting to infinity would not be appropriate for most situations.

Before attempting to calculate the value, check if the divisor (table.ix[:,0] in this case) is equal to zero. If it is, then skip the calculation and just assign whatever value you want.

Or you can wrap the division calculation in a try/except block as suggested by @Andrew.

John Gordon
  • 29,573
  • 7
  • 33
  • 58