Этой заметкой открываю серию статей для начинающих вкатываться в Data Sciеnce и Machine Learning и начнем мы с изучения Pandas. В интернете много статей по Pandas, поэтому хотел бы в этой заметки описать практические приемы для работы с Pandas в Data Sciеnce проектах и для построения моделей.
В качестве датасета будем использовать German Credit Risk на Kaggle
Датасет содержит информацию о кредитных данных:
- Age (возраст)
- Sex (пол)
- Job (работа)
- Housing (тип жилья)
- Saving accounts (сберегательные счета)
- Checking account (расчетный счет)
- Credit amount (сумма кредита)
- Duration (продолжительность кредита)
- Purpose (цель кредита)
Работа с Jupyter Notebook
Прежде чем мы перейдем к Pandas для совсем новичков хочу немного рассказать о работе в среде Jupyter Notebook. Когда вы выполняете код в Jupyter Notebook, результаты вычислений сохраняются в оперативной памяти. Даже если вы удалите ячейку, данные, созданные ею, останутся доступны до тех пор, пока вы не перезапустите ядро (kernel).
В Jupyter Notebook существуют два основных типа ячеек:
- Код: используется для написания и выполнения Python кода.
- Markdown: используется для оформления текста, создания заголовков, списков, ссылок и другого форматированного текста.
Jupyter Notebook предоставляет горячие клавиши, которые ускоряют работу. Например:
Shift + Enter
: выполнить текущую ячейку и перейти к следующей.Ctrl + Enter
: выполнить текущую ячейку и остаться в ней.B
: добавить новую ячейку под текущей.A
: добавить новую ячейку над текущей.
Основы Python для Pandas
А теперь расскажу некоторые принципы и конструкции Python полезные в работе с Pandas.
Циклы
Циклы в Python, такие как for
и while
, позволяют выполнять одни и те же операции несколько раз. При работе с библиотекой Pandas, использование циклов часто бывает неэффективным, особенно для больших наборов данных. Прямое использование циклов в Pandas может существенно замедлить выполнение кода. Например, рассмотрим задачу лемматизации текста (приведение слов к их начальной форме):
import nltk
from nltk.stem import WordNetLemmatizer
from nltk.tokenize import word_tokenize
nltk.download('punkt')
nltk.download('wordnet')
nltk.download('omw-1.4')
def lemmatize(text):
lemmatizer = WordNetLemmatizer()
tokens = word_tokenize(text)
lemmatized_tokens = [lemmatizer.lemmatize(token) for token in tokens]
return ' '.join(lemmatized_tokens)
lemmas = []
for text in data['Purpose']:
lemmas.append(lemmatize(text))
data['Lemmatized'] = lemmas
Теперь тот же пример с использованием метода apply()
:
data['Lemmatized'] = data['Purpose'].apply(lemmatize)
Использование apply()
работает быстрее и требует меньше кода, поскольку Pandas оптимизирует выполнение внутренних операций.
Функции
Функции в Python — это основной инструмент для повторного использования кода. Они позволяют разбивать код на более мелкие части, каждая из которых выполняет одну конкретную задачу.
def
используется для определения именованных функций, которые могут содержать несколько операторов и выполнять сложные операции. Предположим, что у нас есть задача преобразовать возраст клиентов (колонка Age
) в группы по возрасту:
def age_group(age):
if age < 30:
return 'Young'
elif 30 <= age < 60:
return 'Middle-aged'
else:
return 'Senior'
data['Age Group'] = data['Age'].apply(age_group)
lambda
используется для создания анонимных функций, которые обычно содержат одно выражение. Например, предположим, что нам нужно добавить к каждому значению в колонке Credit amount
10%:
data['Adjusted Credit Amount'] = data['Credit amount'].apply(lambda x: x * 1.1)
def
предпочтительнее использовать, когда функция сложна или требует документирования, а lambda
полезен для простых одноразовых задач.
try-except
Конструкция try-except
помогает избежать ошибок, которые могут прервать выполнение программы. Допустим, мы пытаемся преобразовать значения в колонке Credit amount
в целые числа, но некоторые значения могут быть некорректными (например, строки). Используем try-except
, чтобы обрабатывать возможные ошибки:
def safe_convert_to_int(value):
try:
return int(value)
except ValueError:
return None
data['Credit amount (int)'] = data['Credit amount'].apply(safe_convert_to_int)
В этом примере функция safe_convert_to_int()
пытается преобразовать значение в целое число. Если возникает ошибка (например, если значение не является числом), try-except
перехватывает ошибку, и функция возвращает None
.
Pandas для Data Science
И вот мы наконец-то дошли до Pandas. Быстро пробежим по основам.
Pandas позволяет загружать данные из файлов с различными разделителями (разделителями полей). По умолчанию, pd.read_csv()
предполагает, что разделителем является запятая. Если данные разделены другими символами, например, точкой с запятой, табуляцией или пробелом, нужно явно указать это при загрузке файла:
df_semicolon = pd.read_csv('data_semicolon.csv', sep=';')
df_tab = pd.read_csv('data_tab.csv', sep='\\t')
df_space = pd.read_csv('data_space.csv', sep=' ')
Кодировка файлов важна, особенно при работе с данными, содержащими специальные символы или текст на других языках. Если файл закодирован не в UTF-8, нужно указать его кодировку:
df_iso = pd.read_csv('data_iso.csv', encoding='ISO-8859-1')
df_utf16 = pd.read_csv('data_utf16.csv', encoding='utf-16')
Функции обзора данных
После загрузки данных важно быстро понять их структуру и качество. Pandas предоставляет несколько полезных функций для этого.
.info()
выводит краткую информацию о DataFrame: количество записей, количество столбцов, их имена, типы данных и количество ненулевых значений..describe()
выводит статистические сводки по числовым столбцам: среднее значение, стандартное отклонение, минимальное и максимальное значение, квартильные значения..head()
показывает первые 5 строк DataFrame. Можно указать конкретное количество строк для отображения..tail()
показывает последние 5 строк DataFrame..sample()
выбирает случайные строки из DataFrame, что полезно для беглого обзора данных..shape()
возвращает размерность DataFrame, т.е. количество строк и столбцов.
Типы данных
Приведение типов данных в Pandas имеет важное значение по нескольким причинам:
- Оптимизация памяти: Некоторые типы данных занимают меньше памяти. Например, приведение столбцов с текстовыми значениями к типу
category
значительно снижает объем занимаемой памяти по сравнению с типом object
. - Ускорение вычислений: Работа с числовыми типами данных (например,
int
, float
) быстрее и эффективнее, чем с типом object
. Это особенно важно для больших наборов данных. - Корректность операций: Приведение типов помогает избежать ошибок при выполнении операций над данными. Например, операции сравнения или арифметические операции могут работать некорректно, если данные имеют неправильный тип.
Бинарные переменные — это переменные, которые могут принимать только два значения, например, 0
и 1
, True
и False
, или другие эквиваленты (например, Да
и Нет
):
data['Is Male'] = data['Sex'].apply(lambda x: 1 if x == 'male' else 0)
В этом примере создается новая колонка Is Male
, которая содержит 1, если пол клиента — мужской, и 0 — если женский. Бинарные переменные часто используются в моделировании для обозначения наличия или отсутствия какого-либо признака.
Тип данных category
имеет ряд преимуществ по сравнению с object
:
- Меньшее использование памяти: Если столбец имеет небольшое количество уникальных значений, тип
category
хранит эти значения как категории, а не строки, что снижает использование памяти. - Ускорение операций: Операции по сравнению, сортировке и группировке выполняются быстрее с типом
category
из-за оптимизированного внутреннего представления данных. - Понимание данных: Приведение к
category
помогает явно обозначить категориальные признаки, что важно для анализа и моделирования.
data['Sex'] = data['Sex'].astype('category')
Типы данных int
и float
различаются следующим:
int
(целые числа): Используется для представления целых чисел, которые не имеют дробной части. Занимает меньше памяти, чем float
.float
(вещественные числа): Используется для представления чисел с дробной частью. Занимает больше памяти и может быть менее точным из-за особенностей хранения чисел с плавающей запятой.
Когда использовать int
и float
?
- Используйте
int
, если данные всегда будут целыми числами (например, количество товаров, возраст). - Используйте
float
, если возможны дробные значения (например, цены, проценты).
Подробнее о разнице можно почитать по ссылке.
Метод pd.to_numeric()
используется для приведения данных к числовому типу (например, int
или float
). Это полезно, если данные содержат строки, которые могут быть преобразованы в числа.
data['Credit amount'] = pd.to_numeric(data['Credit amount'], errors='coerce')
Если в колонке окажется значение, которое невозможно преобразовать в число, метод заменит его на NaN
(если использовать параметр errors='coerce'
). Это помогает избежать ошибок при анализе и расчете.
Обращение к колонкам
В Pandas можно обращаться к колонкам DataFrame двумя основными способами: через точку (.
) и через квадратные скобки ([]
). Оба метода имеют свои особенности и ограничения.
Обращение через точку (.
) — этот способ удобен и компактен, но он имеет ряд ограничений:
- Работает только для колонок, имена которых не содержат пробелов и специальных символов.
- Не работает, если имя колонки совпадает с именем метода или атрибута DataFrame.
data.Age
Здесь data.Age
возвращает колонку Age
как Series.
Обращение через квадратные скобки ([]
) — это более универсальный способ, так как он не ограничен именами колонок:
- Поддерживает обращение к колонкам с любыми именами, включая те, которые содержат пробелы, специальные символы, или совпадают с методами/атрибутами DataFrame.
- Можно использовать для обращения к нескольким колонкам сразу (передается список колонок).
Примеры:
# Обращение к одной колонке
data['Age']
# Обращение к колонке с именем, содержащим пробел
data['Saving accounts']
# Обращение к нескольким колонкам
data[['Age', 'Credit amount']]
Индексация
Pandas предлагает несколько способов для индексации и выборки данных из DataFrame:
iloc
используется для выборки данных по их позициям (числовым индексам). Работает как для строк, так и для колонок.
Примеры:
# Выбор первой строки (индексация начинается с 0)
data.iloc[0]
# Выбор первых пяти строк
data.iloc[:5]
# Выбор значения в первой строке и втором столбце
data.iloc[0, 1]
# Выбор первых трех строк и первых двух столбцов
data.iloc[:3, :2]
loc
используется для выборки данных по меткам (названиям строк и колонок).
Примеры:
# Выбор строки с индексом 0
data.loc[0]
# Выбор всех строк, где значение в колонке 'Age' равно 30
data.loc[data['Age'] == 30]
# Выбор значения в строке с индексом 0 и колонке 'Age'
data.loc[0, 'Age']
# Выбор первых трех строк и колонок 'Age' и 'Credit amount'
data.loc[:2, ['Age', 'Credit amount']]
Когда используете []
для обращения к строкам (как data[0:5]
), Pandas возвращает строки с номерами от 0 до 4 (выбор по индексу строк). А при обращении к колонке (как data['Age']
), возвращается указанная колонка.
Примеры:
# Выбор первых пяти строк
data[0:5]
# Выбор колонки 'Age'
data['Age']
Фильтрация данных
Фильтрация данных позволяет выбрать строки, соответствующие определенным условиям.
Метод .drop()
используется для удаления строк или колонок. Вы можете указать ось (axis
) для удаления (0 — строки, 1 — колонки).
Примеры:
# Удаление колонки 'Age'
data.drop('Age', axis=1)
# Удаление строк с индексами 0, 1 и 2
data.drop([0, 1, 2], axis=0)
Метод .query()
позволяет фильтровать строки на основе логических условий, написанных как строка.
Пример:
# Выбор всех строк, где 'Age' больше 30 и 'Credit amount' меньше 5000
data.query('Age > 30 & `Credit amount` < 5000')
Вы можете использовать .loc[]
для фильтрации строк, основанной на условии:
Пример:
# Выбор всех строк, где 'Age' больше 30
data.loc[data['Age'] > 30]
В Pandas большинство методов, таких как .drop()
, .fillna()
, .replace()
, имеют параметр inplace
, который, если установлен в True
, модифицирует исходный DataFrame напрямую, а не создает его копию.
Пример использования inplace
:
# Удаление колонки с использованием inplace
data.drop('Age', axis=1, inplace=True)
Опасности:
- Необратимость изменений: При использовании
inplace=True
, изменения в DataFrame выполняются на месте, и если вы случайно удалите или измените данные, это не может быть легко отменено. - Проблемы с цепочкой методов: Если вы используете несколько методов в цепочке,
inplace=True
может вызвать ошибки или нежелательное поведение, так как измененный DataFrame может больше не соответствовать ожидаемым условиям. - Потеря гибкости: Без
inplace
вы можете сохранить исходные данные и новые данные, чтобы иметь возможность сравнить результаты или вернуться к исходным данным, если что-то пойдет не так.
Группировка и сортировка данных
Метод .agg()
используется для выполнения различных агрегатных функций над данными, сгруппированными по одному или нескольким столбцам. Вы можете применять несколько агрегатных функций к нескольким колонкам одновременно.
Пример использования .agg()
:
# Группировка данных по колонке 'Sex' и агрегация по нескольким метрикам
aggregated_data = data.groupby('Sex').agg({
'Age': ['mean', 'min', 'max'], # Для колонки 'Age' вычисляем среднее, минимум и максимум
'Credit amount': ['sum', 'mean'] # Для колонки 'Credit amount' вычисляем сумму и среднее
})
В результате вы получите DataFrame, где для каждой группы (Sex
) будут рассчитаны указанные агрегатные функции для соответствующих колонок.
Метод .sort_values()
позволяет сортировать данные по нескольким колонкам одновременно, причем для каждой колонки можно задать свой порядок сортировки.
Пример:
# Сортировка данных по 'Age' по возрастанию и 'Credit amount' по убыванию
sorted_data = data.sort_values(by=['Age', 'Credit amount'], ascending=[True, False])
Здесь строки будут отсортированы сначала по возрастанию возраста, а затем по убыванию суммы кредита.
Разбивка на категории
Метод .map()
позволяет заменить значения в колонке на основе переданного отображения (словаря) или функции.
Примеры:
# Замена значений в колонке 'Sex' на числовые значения
data['Sex'] = data['Sex'].map({'male': 1, 'female': 0})
# Преобразование значений колонки 'Age' с использованием функции
data['Age group'] = data['Age'].map(lambda x: 'young' if x < 30 else 'adult')
Метод .cut()
используется для разбиения числовых данных на интервалы, создавая новую категориальную переменную.
Пример:
# Разбивка возраста на три группы
data['Age group'] = pd.cut(data['Age'], bins=[0, 30, 50, 100], labels=['young', 'middle-aged', 'senior'])
Здесь возраст будет разбит на три категории: young
(от 0 до 30 лет), middle-aged
(от 30 до 50 лет) и senior
(от 50 до 100 лет).
Категоризация по вхождению строки
Иногда требуется создать новую категорию на основе наличия определенного слова в строке. Это можно сделать с помощью методов Pandas.
Пример:
# Создание новой колонки, которая показывает, содержит ли колонка 'Purpose' слово 'car'
data['Car related'] = data['Purpose'].apply(lambda x: 'car' in x.lower())
В этом примере в колонке Car related
будут значения True
, если в колонке Purpose
встречается слово «car», и False
в противном случае.
Замена данных по условию
Функция np.where()
позволяет заменять значения в зависимости от выполнения условия.
Пример:
import numpy as np
# Замена значений в колонке 'Age' на 'young' если возраст меньше 30, иначе на 'adult'
data['Age category'] = np.where(data['Age'] < 30, 'young', 'adult')
Функция np.select()
позволяет задавать несколько условий для замены значений.
Пример:
conditions = [
(data['Age'] < 30),
(data['Age'] >= 30) & (data['Age'] < 50),
(data['Age'] >= 50)
]
choices = ['young', 'middle-aged', 'senior']
# Присваиваем значения в зависимости от выполнения условий
data['Age group'] = np.select(conditions, choices, default='unknown')
Здесь np.select()
проверяет условия и заменяет значения в колонке Age group
в зависимости от того, какое условие выполняется.
Вы можете использовать стандартное выражение if-else
внутри функции и применять его к данным с помощью метода .apply()
.
Пример:
# Определяем функцию
def age_category(age):
if age < 30:
return 'young'
elif age < 50:
return 'middle-aged'
else:
return 'senior'
# Применяем функцию к колонке 'Age'
data['Age group'] = data['Age'].apply(age_category)
Метод pd.where()
оставляет значения без изменений, если условие выполняется, и заменяет их, если не выполняется.
Пример:
# Замена всех значений в колонке 'Age', где возраст больше 30, на '30+'
data['Age'] = data['Age'].where(data['Age'] > 30, '30+')
Здесь все значения в колонке Age
, где возраст больше 30, будут заменены на строку '30+'
, а остальные значения останутся без изменений.
Плохие данные
При анализе данных часто возникают ситуации, когда определенные значения выделяются из общей массы, являясь аномальными или ошибочными. В рамках исследования, проведенного с использованием вложенного датасета, было обнаружено, что средний стаж работы двух категорий клиентов значительно превышает нормальные значения. Это вызвало обоснованный вопрос: как можно корректно обработать эти данные, чтобы улучшить качество анализа и сделать его результаты более достоверными?
Аномалии в данных могут возникать по разным причинам:
- Ошибки ввода данных: Возможно, при вводе данных в систему произошла ошибка, и значения были записаны неверно. Например, вместо 5 лет стажа могли указать 50.
- Нарушение правил валидации: Если система, которая собирает данные, не имеет достаточных проверок, некорректные значения могут попасть в итоговый датасет.
- Редкие события: Аномалия может отражать реальную, но редкую ситуацию. Например, возможно, что некоторые клиенты действительно обладают большим стажем, но таких случаев мало.
- Системные сбои: В процессе сбора данных могут произойти сбои, приводящие к появлению некорректных значений.
Существует несколько подходов к обработке аномальных или ошибочных данных:
- Удаление аномальных значений: Если значение явно неверное и не поддается исправлению, его можно просто удалить из датасета. Однако, этот метод может привести к потере важной информации.
- Замена значений на среднее или медианное: Если аномальные значения сильно искажают общую картину, их можно заменить на средние или медианные значения для данной категории.
- Использование методов машинного обучения: Некоторые алгоритмы могут автоматически выявлять и обрабатывать аномалии, оставляя только значимые данные для анализа.
- Корректировка значений на основе правил бизнеса: Например, если известно, что максимальный стаж в отрасли не превышает 40 лет, все значения, выходящие за этот предел, можно заменить на 40.
Как это делают в реальной жизни?
На практике часто используют комбинированные методы. Сначала проводится детальный анализ аномальных данных: изучаются возможные причины их возникновения и степень влияния на итоговый результат. В зависимости от контекста, принимается решение о том, стоит ли удалять, корректировать или сохранять такие данные.
В случаях, когда аномалия связана с реальной, но редкой ситуацией, ее могут оставить в данных, но при этом отметить, что это исключение. Если же аномалия связана с ошибкой ввода или системным сбоем, данные корректируются или удаляются.
Давайте теперь перейдем к практике. Выявим аномальные значения в столбце продолжительность кредита. А затем обработаем аномалии, используя один из методов, предложенных ранее.
Аномальные значения можно выявить на основе описательной статистики. Например, значения, которые значительно превышают 3 стандартных отклонения от среднего, можно считать аномальными.
import numpy as np
# Вычисление среднего и стандартного отклонения
mean_duration = data['Duration'].mean()
std_duration = data['Duration'].std()
# Определение границ для аномальных значений
upper_bound = mean_duration + 3 * std_duration
lower_bound = mean_duration - 3 * std_duration
# Фильтрация аномальных значений
anomalies = data[(data['Duration'] > upper_bound) | (data['Duration'] < lower_bound)]
После выявления аномалий можно их обработать разными способами, например, заменить на медианное значение.
# Замена аномальных значений на медианное значение
median_duration = data['Duration'].median()
data['Duration'] = np.where((data['Duration'] > upper_bound) | (data['Duration'] < lower_bound),
median_duration, data['Duration'])
Работа с пропусками в данных
Пропуски в данных могут возникать по разным причинам: ошибки при сборе данных, отсутствие информации или технические сбои. Важно учитывать, что пропуски могут существенно повлиять на результаты анализа, поэтому их необходимо корректно обрабатывать. Пропуски нужно заменять, если:
- Пропуски значительны по количеству: Если количество пропусков в столбце велико, анализ без их учета может быть искажен.
- Пропуски находятся в ключевых переменных: Если пропуски находятся в переменных, которые критически важны для анализа, их необходимо заменить, чтобы сохранить целостность данных.
- Данные необходимы для дальнейшего моделирования: В машинном обучении часто необходимо, чтобы данные были полными, поэтому пропуски нужно заполнять.
Методы замены пропусков зависят от типа данных и контекста:
- Замена средним или медианным значением: Используется для числовых данных, если распределение данных симметрично или имеет выбросы.
- Замена модой (наиболее частым значением): Подходит для категориальных данных.
- Замена значением на основе данных из других колонок: Например, если пропущены значения в колонке зарплаты, их можно заполнить на основе должности, которая указана в другой колонке.
- Использование моделей для предсказания пропусков: Более сложный метод, где пропуски заполняются с помощью предсказательных моделей.
Команды для замены пропусков в Pandas:
data.fillna(value)
– Замена всех пропусков в датафрейме на указанное значение.data['column'].fillna(data['column'].mean(), inplace=True)
– Замена пропусков в конкретной колонке на среднее значение.data['column'].fillna(data['column'].median(), inplace=True)
– Замена пропусков на медианное значение.data.fillna(method='ffill')
– Заполнение пропусков предыдущим значением.data.fillna(method='bfill')
– Заполнение пропусков следующим значением.
# Проверка наличия пропусков
missing_values = data.isnull().sum()
print(missing_values)
После выполнения кода мы увидим, что пропуски есть в колонках Saving accounts и Checking account. Давайте рассмотрим, как можно обработать пропуски в столбце «Checking account» с использованием различных подходов.
Замена на наиболее частое значение (моду): Если категория встречается чаще других, пропуски можно заменить на нее.
# Замена пропусков на наиболее частое значение
most_frequent = data['Checking account'].mode()[0]
data['Checking account'].fillna(most_frequent, inplace=True)
Замена на специальное значение: Пропуски можно заменить на специальное значение, например, «Unknown» или «No account», если это имеет смысл в контексте данных.
# Замена пропусков на 'Unknown'
data['Checking account'].fillna('Unknown', inplace=True)
Замена на основе данных из других колонок: Если в датасете есть другие столбцы, которые могут коррелировать с наличием или типом счета, можно использовать эти данные для заполнения пропусков.
data['Checking account'] = data.groupby('Job')['Checking account'].transform(lambda x: x.fillna(x.mode()[0] if not x.mode().empty else 'Unknown'))
Работа с дубликатами в данных
Дубликаты в данных — это записи, которые полностью или частично повторяются. Наличие дубликатов может искажать результаты анализа, поэтому важно своевременно их обнаруживать и устранять.
В Pandas для поиска дубликатов используется метод duplicated()
, который возвращает логический массив (True или False) для каждой строки, указывая, является ли данная строка дубликатом.
data.duplicated()
— возвращает True для всех строк, которые являются дубликатами (включая первую встреченную запись).data.duplicated(keep='first')
— помечает как дубликаты все строки, кроме первой встретившейся копии.data.duplicated(keep='last')
— помечает как дубликаты все строки, кроме последней встретившейся копии.data.duplicated(keep=False)
— помечает как дубликаты все строки, включая первую и последнюю встреченные копии.
duplicates = data[data.duplicated()]
print(f'Количество дубликатов: {duplicates.shape[0]}')
# Просмотр дубликатов
print(duplicates)
После обнаружения дубликатов можно выбрать один из нескольких методов их обработки:
Удаление дубликатов: Если дубликаты не содержат уникальной информации, их можно удалить.
# Удаление всех дубликатов, оставляя первую встреченную запись
data= data.drop_duplicates(keep='first')
# Проверка количества строк после удаления дубликатов
print(f'Количество строк после удаления дубликатов: {data.shape[0]}')
Агрегация данных: Если дубликаты имеют различающиеся значения в некоторых полях, их можно объединить, например, с помощью среднего или суммы.
# Пример агрегации (взятие среднего значения для числовых столбцов)
df_aggregated = data.groupby(data.columns.tolist(), as_index=False).mean()
Маркировка и дальнейший анализ: В некоторых случаях дубликаты можно оставить, но добавить метку или флаг, чтобы учесть их в дальнейшем анализе.
# Добавление флага для дубликатов
data['is_duplicate'] = data.duplicated(keep=False)
Дубликаты могут возникать по ряду причин:
- Ошибки при сборе данных: Например, если один и тот же клиент был внесен в систему дважды по ошибке.
- Слияние нескольких источников данных: При объединении данных из разных источников одни и те же записи могут появиться несколько раз.
- Повторная загрузка данных: Иногда данные могут быть загружены повторно, что приводит к появлению дубликатов.
- Отсутствие уникальных идентификаторов: Если в данных нет уникальных идентификаторов (например, ID клиентов), система может не различать записи как уникальные, даже если они представляют разных людей или события.
Вывод
В этой заметке я постарался раскрыть все возможные кейсы применения Pandas в Data Sciencе проектах. Описал практические приемы. Все это пригодится вам в следующих статьях из цикла статей для начинающих вкатываться в Data Sciеnce и Machine Learning.
Разговоры о Data Science – закрытый канал для общения на тему карьеры, развития профессиональных навыков и применения навыков на работе.