Відповіді:
Використовувати .loc
для індексування на основі міток:
df.loc[df.A==0, 'B'] = np.nan
df.A==0
Вираз створює логічний ряд , що індекси рядків, 'B'
вибирає стовпець. Ви також можете використовувати це для перетворення підмножини стовпця, наприклад:
df.loc[df.A==0, 'B'] = df.loc[df.A==0, 'B'] / 2
Я не знаю достатньо інтернетів панд, щоб точно знати, чому це працює, але основне питання полягає в тому, що іноді індексація в DataFrame повертає копію результату, а іноді повертає погляд на вихідний об'єкт. Згідно з документацією тут , така поведінка залежить від основної поведінки нумеру. Я виявив, що доступ до всього за одну операцію (а не [одна] [дві]) швидше спрацює для налаштування.
Ось з документів pandas про розширену індексацію:
У розділі буде пояснено саме те, що вам потрібно! Виявляється df.loc
(як .ix був застарілий - як багато вказувалося нижче) можна використовувати для прохолодного нарізання / вибивання фрейму даних. І. Його також можна використовувати для встановлення речей.
df.loc[selection criteria, columns I want] = value
Отже, відповідь Брена говорить: "знайди мені всі місця, де df.A == 0
виберіть стовпчик B
і встановіть його np.nan
"
loc[selection criteria, columns I want]
зовсім прилипає до вашого виду ...
Починаючи з панд 0,20 ix застаріло . Правильний спосіб - використовувати df.loc
ось робочий приклад
>>> import pandas as pd
>>> import numpy as np
>>> df = pd.DataFrame({"A":[0,1,0], "B":[2,0,5]}, columns=list('AB'))
>>> df.loc[df.A == 0, 'B'] = np.nan
>>> df
A B
0 0 NaN
1 1 0
2 0 NaN
>>>
Як пояснено в документі, тут , .loc
в основному, заснована мітка, але також може використовуватися з булевим масивом .
Отже, те, що ми робимо вище, застосовує df.loc[row_index, column_index]
:
loc
може сприймати булевий масив як маску, яка повідомляє пандам, підмножину рядків яких ми хочемо змінитиrow_index
loc
є також мітка на основі вибору стовпця з використанням мітки 'B'
вcolumn_index
Ми можемо використовувати логічну, умовну або будь-яку операцію, яка повертає ряд булів, щоб побудувати масив булевих. У наведеному вище прикладі ми хочемо, щоб будь-який, rows
що містить a 0
, для цього ми можемо використовувати df.A == 0
, як ви бачите в наведеному нижче прикладі, це повертає ряд булів.
>>> df = pd.DataFrame({"A":[0,1,0], "B":[2,0,5]}, columns=list('AB'))
>>> df
A B
0 0 2
1 1 0
2 0 5
>>> df.A == 0
0 True
1 False
2 True
Name: A, dtype: bool
>>>
Потім ми використовуємо вищевказаний масив булевих, щоб вибрати та змінити необхідні рядки:
>>> df.loc[df.A == 0, 'B'] = np.nan
>>> df
A B
0 0 NaN
1 1 0
2 0 NaN
Для отримання додаткової інформації зверніться до документації по передовій індексації тут .
Для масового збільшення швидкості використовуйте функцію NumPy's where.
Створіть двоколонний DataFrame зі 100 000 рядків з деякими нулями.
df = pd.DataFrame(np.random.randint(0,3, (100000,2)), columns=list('ab'))
numpy.where
df['b'] = np.where(df.a.values == 0, np.nan, df.b.values)
%timeit df['b'] = np.where(df.a.values == 0, np.nan, df.b.values)
685 µs ± 6.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit df.loc[df['a'] == 0, 'b'] = np.nan
3.11 ms ± 17.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Numpy's where
приблизно в 4 рази швидший
.values
в np.where(df.a.values == 0, np.nan, df.b.values)
? Схоже, np.where(df.a == 0, np.nan, df.b)
також працює?
Для заміни декількох стовпців перетворіть на numpy масив, використовуючи .values
:
df.loc[df.A==0, ['B', 'C']] = df.loc[df.A==0, ['B', 'C']].values / 2
where
як видно з цього рішення нижче