Найти разницу между 2 столбцами с пустыми значениями, используя панд

Я хочу найти разницу между 2 столбцами типа int в панде DataFrame. Я использую Python 2.7. Столбцы как ниже -

>>> df
   INVOICED_QUANTITY  QUANTITY_SHIPPED
0                 15               NaN
1                 20               NaN
2                  7               NaN
3                  7               NaN
4                  7               NaN

Теперь я хочу вычесть QUANTITY_SHIPPED из INVOICED_QUANTITY, и я делаю следующее:

>>> df['Diff'] = df['QUANTITY_INVOICED'] - df['SHIPPED_QUANTITY']
>>> df
   QUANTITY_INVOICED  SHIPPED_QUANTITY  Diff
0                 15               NaN   NaN
1                 20               NaN   NaN
2                  7               NaN   NaN
3                  7               NaN   NaN
4                  7               NaN   NaN

Как мне позаботиться о NaN? Я хотел бы получить приведенный ниже результат, поскольку я хочу, чтобы значения NaN рассматривались как 0 (ноль)-

>>> df
       QUANTITY_INVOICED  SHIPPED_QUANTITY  Diff
    0                 15               NaN   15
    1                 20               NaN   20
    2                  7               NaN   7
    3                  7               NaN   7
    4                  7               NaN   7

Я не хочу делать df.fillna(0), В общем, я бы попробовал что-то вроде следующего и это работает, но не для разницы -

>>> df['Sum'] = df[['QUANTITY_INVOICED', 'SHIPPED_QUANTITY']].sum(axis=1)
>>> df
   INVOICED_QUANTITY  QUANTITY_SHIPPED  Diff  Sum
0                 15               NaN   NaN   15
1                 20               NaN   NaN   20
2                  7               NaN   NaN    7
3                  7               NaN   NaN    7
4                  7               NaN   NaN    7

3 ответа

Решение

Вы можете использовать sub метод для вычитания - этот метод позволяет NaN значения, которые будут рассматриваться как указанное значение:

df['Diff'] = df['INVOICED_QUANTITY'].sub(df['QUANTITY_SHIPPED'], fill_value=0)

Который производит:

   INVOICED_QUANTITY  QUANTITY_SHIPPED  Diff
0                 15               NaN    15
1                 20               NaN    20
2                  7               NaN     7
3                  7               NaN     7
4                  7               NaN     7

Другой удобный способ сделать это, как предлагает @JianxunLi: заполнить пропущенные значения в столбце (создав копию столбца) и вычесть как обычно.

Два подхода почти одинаковы, хотя sub немного эффективнее, потому что не нужно заранее создавать копию столбца; он просто заполняет пропущенные значения "на лету":

In [46]: %timeit df['INVOICED_QUANTITY'] - df['QUANTITY_SHIPPED'].fillna(0)
10000 loops, best of 3: 144 µs per loop

In [47]: %timeit df['INVOICED_QUANTITY'].sub(df['QUANTITY_SHIPPED'], fill_value=0)
10000 loops, best of 3: 81.7 µs per loop

Я думаю, что простая заливка NaN 0 поможет вам.

df['Diff'] = df['INVOICED_QUANTITY'] - df['QUANTITY_SHIPPED'].fillna(0)

Out[153]: 
   INVOICED_QUANTITY  QUANTITY_SHIPPED  Diff
0                 15               NaN    15
1                 20               NaN    20
2                  7               NaN     7
3                  7               NaN     7
4                  7               NaN     7

Решения, предложенные user3923281 и user5014134 , не работают должным образом, когда оба столбца имеют значение NaN. Вы можете немного пересмотреть это решение @Jianxun Li (за счет некоторого вычислительного времени), чтобы исправить это.

      df['Diff'] = df['INVOICED_QUANTITY'].fillna(0) - df['QUANTITY_SHIPPED'].fillna(0)

Выкладываю несколько вариантов для сравнения:

      data = {'C1':  [1,2,np.nan,np.nan],
        'C2': [6,np.nan,4,np.nan],
       }
df = pd.DataFrame(data)

df['Dif']=df.C1-df.C2
df['Dif2']=df['C1'].sub(df['C2'], fill_value=0)
df['Dif3']=df['C1']-df['C2'].fillna(0)
df['Dif4']=df['C1'].fillna(0)-df['C2']
df['Dif5']=df['C1'].fillna(0)-df['C2'].fillna(0)

print (df)

который производит

           C1    C2    Dif   Dif2   Dif3   Dif4   Dif5
0 1.000 6.000 -5.000 -5.000 -5.000 -5.000 -5.000
1 2.000   NaN    NaN  2.000  2.000    NaN  2.000
2   NaN 4.000    NaN -4.000    NaN -4.000 -4.000
3   NaN   NaN    NaN    NaN    NaN    NaN  0.000
Другие вопросы по тегам