Как оставить NaN после сдвига - PullRequest
0 голосов
/ 17 ноября 2018

У меня есть функция, которая сдвигает значения одного столбца (Col_5) в другой столбец (Col_6), если этот столбец (Col_6) пуст, например:

def shift(row):
    return row['Col_6'] if not pd.isnull(row['Col_6']) else row['Col_5']

Затем я применяю эту функцию кмои столбцы вот так:

df[['Col_6', 'Col_5']].apply(shift, axis=1)

Это работает нормально, но вместо того, чтобы оставить исходное значение в Col_5, мне нужно перейти на Col_6 и вместо него оставить np.nan (чтобы я мог применитьта же функция, что и в предыдущем столбце.) Мысли?

Ответы [ 3 ]

0 голосов
/ 17 ноября 2018
import pandas as pd
import numpy as np
df = pd.DataFrame({'Col_5':[1, np.nan, 3, 4, np.nan],
                   'Col_6':[np.nan, 8, np.nan, 6, np.nan]})
col_5 = df['Col_5'].copy()
df.loc[pd.isnull(df['Col_6']), 'Col_5'] = np.nan
df.loc[pd.isnull(df['Col_6']), 'Col_6'] = col_5

Выход:

# Original Dataframe:
   Col_5  Col_6
0    1.0    NaN
1    NaN    8.0
2    3.0    NaN
3    4.0    6.0
4    NaN    NaN
# Fill Col_5 with NaN where Col_6 is NaN:
   Col_5  Col_6
0    NaN    NaN
1    NaN    8.0
2    NaN    NaN
3    4.0    6.0
4    NaN    NaN
# Assign the original col_5 values to Col_6:
   Col_5  Col_6
0    NaN    1.0
1    NaN    8.0
2    NaN    3.0
3    4.0    6.0
4    NaN    NaN
0 голосов
/ 17 ноября 2018

Настройка (с использованием настройки из @cosmic_inquiry)

df = pd.DataFrame({'Col_5':[1, np.nan, 3, 4, np.nan],
                   'Col_6':[np.nan, 8, np.nan, 6, np.nan]})

Вы можете рассматривать эту проблему как обычную операцию подкачки с mask

numpy.flip + numpy.isnan

a = df[['Col_5', 'Col_6']].values
m = np.isnan(a[:, 1])
a[m] = np.flip(a[m], axis=1)
df[['Col_5', 'Col_6']] = a

np.isnan + loc:

m = np.isnan(df['Col_6'])
df.loc[m, ['Col_5', 'Col_6']] = df.loc[m, ['Col_6', 'Col_5']].values

   Col_5  Col_6
0    NaN    1.0
1    NaN    8.0
2    NaN    3.0
3    4.0    6.0
4    NaN    NaN

Производительность

test_df = \
    pd.DataFrame(np.random.choice([1, np.nan], (1_000_000, 2)), columns=['Col_5', 'Col_6'])

In [167]: %timeit chris(test_df)
68.3 ms ± 291 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [191]: %timeit chris2(test_df)
43.9 ms ± 296 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [168]: %timeit jpp(test_df)
86.7 ms ± 394 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [169]: %timeit cosmic(test_df)
130 ms ± 1.4 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
0 голосов
/ 17 ноября 2018

fillna + mask: векторизация, а не по строкам

В Pandas вы должны попытаться избежать построчных операций с помощью apply, так как они обрабатываются с помощью циклов уровня Python. В этом случае вы можете использовать:

null_mask = df['Col_6'].isnull()
df['Col_6'] = df['Col_6'].fillna(df['Col_5'])
df['Col_5'] = df['Col_5'].mask(null_mask)

Обратите внимание, что мы вычисляем и сохраняем логический ряд, представляющий, где Col_6 равен нулю сначала , а затем используем его позже, чтобы сделать эти значения нулевыми, когда значения были перемещены через fillna.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...