Pandas как найти пустые значения

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

Конечно, каждая ситуация отличается и должна оцениваться по-разному.

Есть много способов справиться с недостающими значениями. Рассмотрим типичные варианты на примере набора данных – ‘Titanic’. Эти данные являются открытым набором данных Kaggle.

Для анализа необходимо импортировать библиотеки Python и загрузить данные.

Для загрузки используется метод Pandas read.csv(). В скобках указывается путь к файлу в кавычках, чтобы Pandas считывал файл во фрейм данных (Dataframes – df) с этого адреса. Путь к файлу может быть URL адрес или вашим локальным адресом файла.

# import the libraries
import pandas as pd
import numpy as np

import matplotlib.pyplot as plt
import seaborn as sns

%matplotlib inline
import matplotlib as plt
import matplotlib as mpl
import matplotlib.cm as cm 
import matplotlib.pyplot as plt
from matplotlib import pyplot

# import the dataset
train_df = pd.read_csv(r'C:UsersTatianaDesktopPythontitanictrain.csv')
train_df.head(2)

Показывает первые 2 строки загруженного фрейма данных

Показывает первые 2 строки загруженного фрейма данных

Посмотрим на размер данных (количество строк, колонок):

train_df.shape

(891, 12)

Для просмотра статистической сводки каждого столбца, чтобы узнать распределение данных в каждом столбце используется метод describe( ). Этот метод показывает нам количество строк в столбце – count, среднее значение столбца – mean, столбец стандартное отклонение – std, минимальные (min) и максимальные (max) значения, а также границу каждого квартиля – 25%, 50% и 75%. Любые значения NaN автоматически пропускаются.

train_df.describe()

метод describe( )

метод describe( )

По умолчанию, метод describe( ) пропускает строки и столбцы не содержащие чисел – категориальные признаки. Чтобы включить сводку по всем столбцам нужно в скобках добавить аргумент – include = “all”.

# describe all the columns
train_df.describe(include = "all")

метод describe(include = "all")

метод describe(include = “all”)

Для категориальных признаков этот метод показывает: – Сколько уникальных значений в наборе данных – unique; top значения; частота появления значений – freg.

Метод info( ) – показывает информацию о наборе данных, индекс, столбцы и тип данных, ненулевые значения и использование памяти.

# look at the info
print(train_df.info())

показывает информацию о наборе данных, индекс, столбцы и тип данных, ненулевые значения и использование памяти.

показывает информацию о наборе данных, индекс, столбцы и тип данных, ненулевые значения и использование памяти.

В результате мы видим, что все колонки, кроме колонок ‘Age’, ‘Cabin’ и ‘Embarked’, содержат по 891 строк.

Колонка ‘Survived’ – это целевое значение. Показывает, кто выжил, а кто – нет. Эта колонка заполнена бинарными значениями:

0 – не выжил

1 – выжил

Метод – value_counts(). Подсчет значений – это хороший способ понять, сколько единиц каждой характеристики / переменной у нас есть.

train_df['Survived'].value_counts()

подсчет значений в колонке 'Survived'

подсчет значений в колонке ‘Survived’

Из 891 пассажира выжило 342.

sns.set_style('whitegrid')
sns.countplot(x='Survived',data=train_df,palette='RdBu_r')

график подсчет значений в колонке 'Survived'

график подсчет значений в колонке ‘Survived’

Из 891 пассажира выжило 342 это 38%.

figure, survive_bar = plt.subplots(figsize=(7, 7))
sns.barplot(x= train_df["Survived"].value_counts().index, y = train_df["Survived"].value_counts(), ax = survive_bar)
survive_bar.set_xticklabels(['Not Survived', 'Survived'])
survive_bar.set_ylabel('Frequency Count')
survive_bar.set_title('Count of Survival', fontsize = 16)

for patch in survive_bar.patches:
    label_x = patch.get_x() + patch.get_width()/2  # find midpoint of rectangle
    label_y = patch.get_y() + patch.get_height()/2
    survive_bar.text(label_x, label_y,
                #left - freq below - rel freq wrt population as a percentage
               str(int(patch.get_height())) + '(' +
               '{:.0%}'.format(patch.get_height()/len(train_df.Survived))+')',
               horizontalalignment='center', verticalalignment='center')

График подсчет значений в колонке 'Survived'

График подсчет значений в колонке ‘Survived’

Визуализация: Графики подсчета значений в колонках – “Survived”, “Pclass”, “Sex”, “SibSp”, “Parch”, “Embarked”

fig, myplot = plt.subplots(figsize = (15,6), nrows = 2,ncols = 3)

features = ["Survived","Pclass","Sex","SibSp","Parch","Embarked"]

row, col, num_cols = 0,0,3

for u in features:
    sns.barplot(x = train_df[u].value_counts().index,y = train_df[u].value_counts(),
                ax  = myplot[row, col])
    myplot[row, col].set_xlabel("")
    myplot[row, col].set_title(u + " Titanic", fontsize = 15)
    myplot[row, col].set_ylabel("Count")
    col = col + 1
    if col == 3:
        col = 0
        row = row + 1

plt.subplots_adjust(hspace = 0.5)
plt.subplots_adjust(wspace = 0.3)
# i put roundbracket around x,y,z to make more sense. just like how x in [1,2,3] 
# and if x is a tuple or bracket
#we have   u in [(1,2,3),(2,3,5),...] where u = (x,y,z)

#for each patch in each graph from [0,0] to [1,2], we want to do the following...
for v in range(2):
    for z in range(3):
        for patch in myplot[v,z].patches:
            label_x = patch.get_x() + patch.get_width()/2  # find midpoint of rectangle
            label_y = patch.get_y() + patch.get_height()/2
            myplot[v,z].text(label_x, label_y, 
                             str(int(patch.get_height())) + '('+'{:.0%}'.format(
                               patch.get_height()/len(train_df.Survived))+')',
                            horizontalalignment='center', verticalalignment='center')

Графики подсчета значений в колонках - "Survived", "Pclass", "Sex", "SibSp", "Parch", "Embarked"

Графики подсчета значений в колонках – “Survived”, “Pclass”, “Sex”, “SibSp”, “Parch”, “Embarked”

Теперь посмотрим на колонки которые имеют пропущенные значения.

Есть два метода обнаружения недостающих данных: – isnull() и notnull().

Результатом является логическое значение, указывающее, действительно ли значение, переданное в аргумент, отсутствует. «Истина» ( True ) означает, что значение является отсутствующим значением, а «Ложь» ( False ) означает, что значение не является отсутствующим.

# Evaluating for Missing Data
missing_data = train_df.isnull()
missing_data.head(6)

True - пропущенные значения

True – пропущенные значения

Используя цикл for в Python, мы можем быстро определить количество пропущенных значений в каждом столбце. Как упоминалось выше, «Истина» представляет отсутствующее значение, а «Ложь» означает, что значение присутствует в наборе данных. В теле цикла for метод “.value_counts ()” подсчитывает количество значений “True”.

# Count missing values in each column
for column in missing_data.columns.values.tolist():
    print(column)
    print(missing_data[column].value_counts())
    print(" ")

количество пропущенных значений в каждом столбце.

количество пропущенных значений в каждом столбце.
количество пропущенных значений в каждом столбце.
количество пропущенных значений в каждом столбце.

Посмотрим – сколько пропущенных значений в каждой колонке.

train_df.isnull().sum()

количество пропущенных значений в каждом столбце.

количество пропущенных значений в каждом столбце.

‘Age’

В колонке возраст – ‘Age’ не указано 177 значений. И нужно понять – это систематическая ошибка или какая-то случайная погрешность.

Н-р, может у пассажиров 1 класса (или у женщин) не спрашивали про возраст ( т. к. это было не прилично), или случайно пропустили. Понимание о причине пропущенных значений, определит – как работать с этими отсутствующими данными.

Нужно сгруппировать возраст, относительно того, отсутствует возраст или нет. Для группировки используем метод groupby().

True – отсутствует возраст

False – значение заполнено

# missing age or not
train_df.groupby(train_df['Age'].isnull()).mean()

метод groupby().  True - отсутствует возраст, False - значение заполнено

метод groupby(). True – отсутствует возраст, False – значение заполнено

Среди пассажиров, у которых значение возраста отсутствовало, были выжившие (около 30%) и погибшие (около 70%) – колонка ‘Survived’, True = 0.29 .

Эти пассажиры были в более низком классе:

  • колонка ‘Pclass’ – True = 2.59 (это среднее значение класса)

  • колонка ‘Fare’ – True = 22.15 (это среднее значение стоимости билета)

Подсчет значений в колонке ‘Pclass’:

# Value Counts
train_df['Pclass'].value_counts()

Подсчет значений в колонке  'Pclass'

Подсчет значений в колонке ‘Pclass’

Например, в 3 классе было 491 пассажира (это 55%)

train_df.groupby(['Pclass']) ['Survived'].value_counts(normalize=True)

Выживаемость пассажиров по классам

Выживаемость пассажиров по классам

Для более детального анализа, создадим новую колонку ‘Age_NaN’ (бинарный классификатор). Используем метод where(), где прописываем условие: – если значение в колонке ‘Age’ отсутствует, то присваиваем в колонке ‘Age_NaN’ – значение 0, если присутствует, то 1.

# Let's create a new column 'Age_NaN'
# If there is no value in the "Age" column, then = 0 and yes value = 1
train_df['Age_NaN'] = np.where(train_df['Age'].isnull(), 0,1)
train_df.head(6)

первые 6 строк фрейма данных с новой колонкой 'Age_NaN'

первые 6 строк фрейма данных с новой колонкой ‘Age_NaN’

Подсчет значений в колонке ‘Age_NaN’

# Value Counts
train_df['Age_NaN'].value_counts()

Подсчет значений в колонке 'Age_NaN'

Подсчет значений в колонке ‘Age_NaN’

Выживаемость пассажиров в зависимости от наличия записи о возрасте.

# Survived passengers by 'Age_NaN'
train_df.groupby(['Age_NaN']) ['Survived'].value_counts(normalize=True)

Выживаемость пассажиров  в зависимости от наличия записи о возрасте.

Выживаемость пассажиров в зависимости от наличия записи о возрасте.

И снова мы видим: – что, среди пассажиров, у которых значение возраста отсутствовало, были выжившие (около 30%) и погибшие (около 70%).

Выживаемость пассажиров в зависимости от наличия записи о возрасте и класса.

train_df.groupby(['Age_NaN','Pclass']) ['Survived'].value_counts(normalize=True)

Выживаемость пассажиров  в зависимости от наличия записи о возрасте и класса.

Выживаемость пассажиров в зависимости от наличия записи о возрасте и класса.
pd.crosstab(train_df['Pclass'], train_df['Age_NaN'])

   зависимость от наличия записи о возрасте  и класса.

зависимость от наличия записи о возрасте и класса.

В первом классе запись отсутствует у 30 пассажиров. Из 30 пассажиров выжило – 46%(14 пассажиров), погибло – 53%(16 пассажиров). Всего пассажиров было в первом классе – 216 (в данном наборе данных).

Во втором классе запись отсутствует у 11 пассажиров. Из 11 пассажиров выжило – 36%(4 пассажира), погибло – 63% (7 пассажиров). Всего пассажиров было во втором классе – 184 (в данном наборе данных).

В третьем классе запись отсутствует у 136 пассажиров. Из 136 пассажиров выжило – 25% (34 пассажира), погибло – 75% (102 пассажира). Всего пассажиров было в третьем классе – 491 (в данном наборе данных).

Выживаемость пассажиров в зависимости от наличия записи о возрасте и пола.

train_df.groupby(['Age_NaN','Sex']) ['Survived'].value_counts(normalize=True)

Выживаемость пассажиров  в зависимости от наличия записи о возрасте и пола.

Выживаемость пассажиров в зависимости от наличия записи о возрасте и пола.
pd.crosstab(train_df['Sex'], train_df['Age_NaN'])

 зависимость от наличия записи о возрасте и пола.

зависимость от наличия записи о возрасте и пола.

У 53 женщин нет записи о возрасте. Из 53 женщин выжило 68% (36 женщин), погибло 32% (17 женщин). Всего женщин было – 314 (в данном наборе данных).

У 124 мужчин нет записи о возрасте. Из 124 мужчин выжило 13% (16 мужчин), погибло 87% (108 мужчин). Всего мужчин было – 577 (в данном наборе данных)

Пассажиров было много в 3 классе и много погибло. Пассажиры – мужчины, у которых был более дешевый билет и более низкий класс – имели меньше шансов выжить.

Т.к. среди пассажиров, у которых значение возраста отсутствовало, были выжившие (около 30%) и погибшие (около 70%), и пассажиры были с разных классов( из 3 класса было значительно больше), и среди пассажиров были мужчины и женщины (мужчин было значительно больше), то при опросе у выживших и при осмотре тел погибших могли случайно пропустить возраст пассажира.

Следовательно делаем вывод, что возраст случайно не занесли.

Решение: Пропущенные значения заполнить средним значением.

# missing values are replaced by the average value
train_df['Age'].fillna(train_df['Age'].mean(), inplace = True)

sns.set_style('whitegrid')
%matplotlib inline

g = sns.FacetGrid(train_df, col='Survived')
g.map(plt.hist, 'Age', bins=10)

график выживаемости пассажиров в зависимости от возраста

график выживаемости пассажиров в зависимости от возраста

Посмотрим на график выживаемости пассажиров в зависимости от класса и возраста

# Survived passengers by Pclass and Age
grid = sns.FacetGrid(train_df, col ='Survived', row ='Pclass', height = 3.5, aspect=1.5)
grid.map(plt.hist, 'Age', alpha=.5, bins=10)
grid.add_legend();

график выживаемости пассажиров в зависимости от класса и возраста

график выживаемости пассажиров в зависимости от класса и возраста

‘Cabin’

В колонке каюта ( ‘Cabin’) не указано 687 значений. Т. к. пропущенных значений много, можно удалить полностью колонку ‘Cabin’, а можно и оставить отсутствующие данные как – отсутствующие данные. Здесь важно понять: – Существует ли какая-то систематическая взаимосвязь между выживанием и тем, была ли у пассажира отдельная каюта.Для группировки используем метод groupby().

True – отсутствует упоминание о каюте

False – значение заполнено

#  missing cabin or not
# Relationship between the presence of a value in the "Cabin" column on the survival rate
train_df.groupby(train_df['Cabin'].isnull()).mean()

метод groupby(). True - отсутствует упоминание о каюте, False - значение заполнено

метод groupby(). True – отсутствует упоминание о каюте, False – значение заполнено

Те, пассажиры у кого запись отсутствует – выжили около 30%. А у кого запись о наличии каюты есть – выжило 67%.

Вывод: Есть взаимосвязь между выживанием и наличием каюты.

Решение:

Создать новую колонку ‘Cabin_available’ (бинарный классификатор).Используем метод where(), где прописываем условие: – Если значение в колонке ‘Cabin’ отсутствует, то присваиваем в колонке ‘Cabin_available’ – значение 0, если присутствует, то 1.

# Let's create a new column 'Cabin_available'
# If there is no value in the "Cabin" column, then = 0 and yes value = 1
train_df['Cabin_available'] = np.where(train_df['Cabin'].isnull(), 0,1)
train_df.head(6)

показывает первые 6 строк фрейма данных с новой колонкой 'Cabin_available'

показывает первые 6 строк фрейма данных с новой колонкой ‘Cabin_available’

Выживаемость пассажиров в зависимости от наличия записи о каюте:

train_df.groupby(['Cabin_available']) ['Survived'].value_counts(normalize=True)

Выживаемость пассажиров в зависимости от наличия записи о каюте

Выживаемость пассажиров в зависимости от наличия записи о каюте
train_df.pivot_table(
  'PassengerId', 'Cabin_available', 'Survived', 'count').plot(
  kind='bar', stacked=True)

График выживаемости пассажиров в зависимости от наличия записи о каюте

График выживаемости пассажиров в зависимости от наличия записи о каюте

Теперь колонку ‘Cabin’ можно удалить.

train_df.drop(['Cabin'], axis = 1, inplace = True)
train_df

фрейм данных без колонки 'Cabin'

фрейм данных без колонки ‘Cabin’

‘Embarked’

В колонке порт посадки на борт (‘Embarked’) не указано два значения. Это категориальный признак.

Решение: Заменить пропущенные значения по частоте. Заменить отсутствующее значение значением, которым чаще всего встречается в конкретном столбце.

train_df['Embarked'].value_counts()

подсчет значений в колонке 'Embarked'

подсчет значений в колонке ‘Embarked’

Чаще всего встречается значение S – 644. Нужно заменить пропущенные значения на S.

# replace the missing 'Embarked' values by the most frequent - S
train_df['Embarked'].replace(np.nan, 'S', inplace = True)
train_df['Embarked'].describe()

метод describe() для колонки 'Embarked', после замены пропущенных значений.

метод describe() для колонки ‘Embarked’, после замены пропущенных значений.

Good! Now, we have a dataset with no missing values. (Хорошо! Теперь у нас есть набор данных без пропущенных значений.)

train_df.isnull().sum()

набор данных без пропущенных значений

набор данных без пропущенных значений

При работе с Dataframe в Pandas можно столкнуться с ситуацией, когда данные не полные (отсутствует часть значений) и это не позволяет их анализировать. В этом уроке мы рассмотрим, как найти строки в Dataframe, у которых часть информации отсутствует.

Как найти строки с отсутствующими данными в Pandas Dataframe

Для начала давайте загрузим наш учебный пример:

import pandas as pd
url=’https://drive.google.com/file/d/1KXfupiJKql5Lc-D73KiiS_jEd_CNIW44/view?usp=sharing’
url2=’https://drive.google.com/uc?id=’ + url.split(‘/’)[-2]
df = pd.read_csv(url2)
df.info()

Как найти строки с отсутствующими данными в Pandas Dataframe

Это база данных по приложениям в Google Play и как вы видите, к примеру в столбце Rating, много пустых элементов.
Для отбора строк, где в одном указанном столбце, отсутствуют данные, мы можем воспользоваться стандартным инструментом фильтрации. К примеру, отберем те строки, по которым в столбце Current Ver нет информации:

df[df[‘Current Ver’].isnull()]

Как найти строки с отсутствующими данными в Pandas Dataframe

Однако, что делать, если нам нужно отобрать все строки, в которых хотя бы в одном из столбцов отсутствуют значения?
Для начала создадим новый Dataframe, в который поместим проверку на то, является ли информация в ячейке пустой или нет:

is_null = df.isnull()

Для каждой позиции мы получим результат False или True, где False – в ячейке есть данные, True – в ячейке NaN.
Как мы видели выше, в 15 строке у нас отсутствует информация о Current Ver, давайте проверим при помощи функции iloc, какие данные по 15 строке у нас в Dataframe is_null:

is_null.iloc[15,]

Как найти строки с отсутствующими данными в Pandas Dataframe

Все верно, по всем столбцам, кроме Current Ver, у нас False, а по столбцу Current Ver у нас True, так как в нем нет какой-либо информации.
Далее нам надо сформировать Series, которая нам послужит в дальнейшем фильтром, в которой значение True будет в случае, если хотя бы в одном столбце в строке нет данных, а False, если информация есть во всех столбцах:

row_with_null = is_null.any(axis=1)

Используя эту Series как фильтр, мы создаем новый Dataframe, в который переносим только те строки, в которых хотя бы в одном из столбцов есть NaN:

rows_with_null = df[row_with_null]

Как найти строки с отсутствующими данными в Pandas Dataframe

Готово, мы нашли все строки с отсутствующими данными в Dataframe. В качестве бонуса прикладываю

ноутбук

с текущего урока. Спасибо за внимание, комментарии приветствуются.

Выявление и фильтрация незаполненных значений с помощью Pandas

Рассмотрим задачу выявления и удаления незаполненных значений, которые в Pandas обозначаются служебным значением NaN. В демонстрационных целях будем использовать набор объявлений о продажах квартир в Республике Северная Осетия-Алания, имеющий следующий вид:

Выявление и фильтрация незаполненных значений с помощью Pandas

Для определения незаполненных значений используются методы isnull, notnull, возвращающие True/False для каждого объекта (обычно значение в столбце или элемент в строке) в зависимости от присутствия в нем пропущенных значений. Например, выведем строку нашей таблицы, в которой значение date_time не заполнено:

Выявление и фильтрация незаполненных значений с помощью Pandas

Для удаления незаполненных значений служит метод dropna, который позволяет задать ось удаления (строки, столбцы); порог минимального количества заполненных значений для принятия решения об удалении; подмножество полей, для которых удаляются незаполненные значения. Эти возможности реализуются посредством следующих параметров:

axis – определяет будут удаляться строки (значение 0) или столбцы (1) с недостающими значениями;

how – условие удаления при всех пустых значениях (значение all) или хотя бы одном (any);

thresh – пороговое количество непустых значений, меньше которого требуется удаление;

subset – задает группы имен столбцов или строк для удаления нулевых значений;

Например, так можно удалить строки, в которых столбец date_time содержит пустое значение (такая всего одна):

Выявление и фильтрация незаполненных значений с помощью Pandas

Другой пример – мы располагает таблицей со значениями нетипичного изменения стоимости недвижимости за неделю в различных категориях площадей (подробнее описывалось в статье), имеющей следующий вид:

Выявление и фильтрация незаполненных значений с помощью Pandas

Для того, чтобы оставить записи с количеством ненулевых значений не менее 3, потребуется вызвать метод dropna(thresh = 3). В результате получается таблица следующего вида:

Выявление и фильтрация незаполненных значений с помощью Pandas

Зачастую некоторые объекты с отсутствующими значениями следует сохранить и заполнить разумными значениями. Например, в таблице цен на недвижимость ячейки с отсутствующей «жилой площадью» («live_square») можно заполнить средним значением по жилым площадям в строках, «общая площадь» («total_square») в которых попадала в тот же диапазон что и в заданной. Это реализуется в следующем коде:

# очищаем столбцы и приводим их содержимое к типу с плавающей

# точкой

df.loc[df[‘total_square’].notnull(), ‘total_square’] = df.loc[df[‘total_square’].notnull(), ‘total_square’].map(
lambda x: x.replace(
‘м²’, ))
df.loc[df[
‘live_square’].notnull(), ‘live_square’] = df.loc[df[‘live_square’].notnull(), ‘live_square’].map(
lambda x: x.replace(
‘м²’, ))
df[
‘total_square’] = df[‘total_square’].astype(np.float32)
df[
‘live_square’] = df[‘live_square’].astype(np.float32)

# ставим в соответствие каждому значению общей площади квартиры

# соответствующий ей диапазон

bins = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 1000]
cat = pd.cut(df[
‘total_square’], bins)

# задаем столбец, содержащий среднее жилой площади для каждого

# диапазона

live_sq = df[‘live_square’].groupby(cat).transform(np.mean)

# для пустых ячеек с жил площадью вставляем значение, полученное на предыдущем шаге

df[‘live_square’] = np.where(df[‘live_square’].isnull(), live_sq, df[‘live_square’])

Отмечу, что способы разбивки по диапазонам значений (например, функция pandas.cut) описывались в статье, а обработка отдельных значений (метод map) в статье.

Напоследок продемонстрирую результаты преобразования нашей таблицы после выполнения указанного выше участка кода:

Выявление и фильтрация незаполненных значений с помощью Pandas

If you want to get True/False for each line, you can use the following code. Here is an example as a result for the following DataFrame:

df = pd.DataFrame([[None, 3], ["", np.nan]])

df
#      0      1
#0  None    3.0
#1          NaN

How to check None

Available: .isnull()

>>> df[0].isnull()
0     True
1    False
Name: 0, dtype: bool

Available: .apply == or is None

>>> df[0].apply(lambda x: x == None)
0     True
1    False
Name: 0, dtype: bool

>>> df[0].apply(lambda x: x is None)
0     True
1    False
Name: 0, dtype: bool

Available: .values == None

>>> df[0].values == None
array([ True, False])

Unavailable: is or ==

>>> df[0] is None
False

>>> df[0] == None
0    False
1    False
Name: 0, dtype: bool

Unavailable: .values is None

>>> df[0].values is None
False

How to check np.nan

Available: .isnull()

>>> df[1].isnull()
0    False
1     True
Name: 1, dtype: bool

Available: np.isnan

>>> np.isnan(df[1])
0    False
1     True
Name: 1, dtype: bool

>>> np.isnan(df[1].values)
array([False,  True])

>>> df[1].apply(lambda x: np.isnan(x))
0    False
1     True
Name: 1, dtype: bool

Unavailable: is or == np.nan

>>> df[1] is np.nan
False

>>> df[1] == np.nan
0    False
1    False
Name: 1, dtype: bool

>>> df[1].values is np.nan
False

>>> df[1].values == np.nan
array([False, False])

>>> df[1].apply(lambda x: x is np.nan)
0    False
1    False
Name: 1, dtype: bool

>>> df[1].apply(lambda x: x == np.nan)
0    False
1    False
Name: 1, dtype: bool

As part of our data wrangling process we might need to find, replace or even drop empty values in our data set so that these values don’t impact our analysis.

In this short tutorial, we’ll learn a few ways to use Python and the Pandas library to query our data and find data rows containing empty values.

Creating our example Data set

We’ll start by importing the Pandas library and creating a very simple dataset that you can use to follow along:

import pandas as pd
import numpy as np

city =  ['DTW', 'NYC', 'SFO','ORD']
office =  ['West', 'North', np.nan, 'East']
interviews = [10,104,210,np.nan]

#create the pandas dataframe
data_dict = dict(city=city, office=office, interviews=interviews)
hr = pd.DataFrame (data_dict)

print(hr.head())

Here’s our DataFrame:

city office interviews
0 DTW West 10.0
1 NYC North 104.0
2 SFO NaN 210.0
3 ORD East NaN

Find rows with null values in Pandas Series (column)

To quickly find cells containing nan values in a specific Python DataFrame column, we will be using the isna() or isnull() Series methods.

Using isna()

nan_in_col  = hr[hr['interviews'].isna()]

Using isnull()


nan_in_col  = hr[hr['interviews'].isnull()]

Both methods will render the following result:

print(nan_in_col)
city office interviews
3 ORD East NaN

Select rows with missing values in a Pandas DataFrame

If we want to quickly find rows containing empty values in the entire DataFrame, we will use the DataFrame isna() and isnull() methods, chained with the any() method.

nan_rows  = hr[hr.isna().any(axis=1)]

or

nan_rows  = hr[hr.isnull().any(axis=1)]

Alternatively we can use the loc indexer to filter out the rows containing empty cells:


nan_rows  = hr.loc[hr.isna().any(axis=1)]

All the above will render the following results:

print(nan_rows)
city office interviews
2 SFO NaN 210.0
3 ORD East NaN

Select DataFrame columns with NAN values

You can use the following snippet to find all columns containing empty values in your DataFrame.


nan_cols = hr.loc[:,hr.isna().any(axis=0)]

Find first row containing nan values

If we want to find the first row that contains missing value in our dataframe, we will use the following snippet:

hr.loc[hr.isna().any(axis=1)].head(1)

Replace missing nan values with zero

Once found, we might decide to fill or replace the missing values according to specific login. We typically use the fillna() DataFrame or Series method for that. In this example we’ll going to replace the missing values in the interview column with 0.

hr.fillna({'interviews':0},  inplace=True)

Additional learning

  • How to replace values in Pandas DataFrame columns?

Добавить комментарий