Notepad-cheat sheet để xử lý trước dữ liệu nhanh chóng

Thông thường những người tham gia vào lĩnh vực Khoa học dữ liệu có ít kỳ vọng thực tế hơn về những gì đang chờ đợi họ. Nhiều người nghĩ rằng bây giờ họ sẽ viết ra những mạng lưới thần kinh thú vị, tạo ra trợ lý giọng nói từ Iron Man hoặc đánh bại tất cả mọi người trên thị trường tài chính.
Nhưng làm việc Ngày Nhà khoa học làm việc dựa trên dữ liệu và một trong những khía cạnh quan trọng và tốn thời gian nhất là xử lý dữ liệu trước khi đưa dữ liệu vào mạng lưới thần kinh hoặc phân tích dữ liệu theo một cách nhất định.

Trong bài viết này, nhóm của chúng tôi sẽ mô tả cách bạn có thể xử lý dữ liệu nhanh chóng và dễ dàng bằng mã và hướng dẫn từng bước. Chúng tôi đã cố gắng làm cho mã khá linh hoạt và có thể được sử dụng cho các bộ dữ liệu khác nhau.

Nhiều chuyên gia có thể không tìm thấy điều gì đặc biệt trong bài viết này, nhưng những người mới bắt đầu sẽ có thể học được điều gì đó mới và bất kỳ ai từ lâu đã mơ ước tạo ra một cuốn sổ tay riêng để xử lý dữ liệu có cấu trúc và nhanh chóng có thể sao chép mã và định dạng nó cho chính họ, hoặc tải xuống sổ ghi chép đã hoàn thành từ Github.

Chúng tôi đã nhận được tập dữ liệu. Phải làm gì tiếp theo?

Vì vậy, tiêu chuẩn: chúng ta cần hiểu những gì chúng ta đang giải quyết, bức tranh tổng thể. Để làm điều này, chúng tôi sử dụng pandas để xác định các loại dữ liệu khác nhau một cách đơn giản.

import pandas as pd #импортируем pandas
import numpy as np  #импортируем numpy
df = pd.read_csv("AB_NYC_2019.csv") #читаем датасет и записываем в переменную df

df.head(3) #смотрим на первые 3 строчки, чтобы понять, как выглядят значения

Notepad-cheat sheet để xử lý trước dữ liệu nhanh chóng

df.info() #Демонстрируем информацию о колонках

Notepad-cheat sheet để xử lý trước dữ liệu nhanh chóng

Hãy xem xét các giá trị cột:

  1. Số dòng trong mỗi cột có tương ứng với tổng số dòng không?
  2. Bản chất của dữ liệu trong mỗi cột là gì?
  3. Chúng ta muốn nhắm mục tiêu vào cột nào để đưa ra dự đoán cho cột đó?

Câu trả lời cho những câu hỏi này sẽ cho phép bạn phân tích tập dữ liệu và phác thảo sơ bộ kế hoạch cho các hành động tiếp theo của bạn.

Ngoài ra, để có cái nhìn sâu hơn về các giá trị trong mỗi cột, chúng ta có thể sử dụng hàm pandas description(). Tuy nhiên, nhược điểm của hàm này là không cung cấp thông tin về các cột có giá trị chuỗi. Chúng ta sẽ giải quyết chúng sau.

df.describe()

Notepad-cheat sheet để xử lý trước dữ liệu nhanh chóng

Hình dung ma thuật

Hãy xem nơi chúng ta không có giá trị nào cả:

import seaborn as sns
sns.heatmap(df.isnull(),yticklabels=False,cbar=False,cmap='viridis')

Notepad-cheat sheet để xử lý trước dữ liệu nhanh chóng

Đây là một cái nhìn ngắn từ trên cao, bây giờ chúng ta sẽ chuyển sang những điều thú vị hơn

Hãy thử tìm và nếu có thể, hãy xóa các cột chỉ có một giá trị trong tất cả các hàng (chúng sẽ không ảnh hưởng đến kết quả theo bất kỳ cách nào):

df = df[[c for c
        in list(df)
        if len(df[c].unique()) > 1]] #Перезаписываем датасет, оставляя только те колонки, в которых больше одного уникального значения

Bây giờ chúng tôi bảo vệ bản thân và sự thành công của dự án khỏi các dòng trùng lặp (các dòng chứa cùng thông tin theo cùng thứ tự với một trong các dòng hiện có):

df.drop_duplicates(inplace=True) #Делаем это, если считаем нужным.
                                 #В некоторых проектах удалять такие данные с самого начала не стоит.

Chúng tôi chia tập dữ liệu thành hai: một có giá trị định tính và một có giá trị định lượng

Ở đây chúng ta cần làm rõ một điều nhỏ: nếu các dòng có dữ liệu bị thiếu trong dữ liệu định tính và định lượng không có mối tương quan nhiều với nhau, thì chúng ta sẽ cần phải quyết định những gì chúng ta hy sinh - tất cả các dòng có dữ liệu bị thiếu, chỉ một phần trong số đó, hoặc một số cột nhất định. Nếu các đường tương quan với nhau thì chúng ta có quyền chia tập dữ liệu thành hai. Nếu không, trước tiên bạn sẽ cần xử lý các dòng không tương quan với dữ liệu còn thiếu về mặt định tính và định lượng, sau đó chỉ chia tập dữ liệu thành hai.

df_numerical = df.select_dtypes(include = [np.number])
df_categorical = df.select_dtypes(exclude = [np.number])

Chúng tôi làm điều này để giúp chúng tôi xử lý hai loại dữ liệu khác nhau này dễ dàng hơn - sau này chúng tôi sẽ hiểu điều này giúp cuộc sống của chúng tôi dễ dàng hơn nhiều như thế nào.

Chúng tôi làm việc với dữ liệu định lượng

Điều đầu tiên chúng ta nên làm là xác định xem có “cột gián điệp” trong dữ liệu định lượng hay không. Chúng tôi gọi những cột này là vì chúng thể hiện dưới dạng dữ liệu định lượng nhưng hoạt động như dữ liệu định tính.

Làm thế nào chúng ta có thể xác định được chúng? Tất nhiên, tất cả phụ thuộc vào bản chất của dữ liệu bạn đang phân tích, nhưng nhìn chung các cột như vậy có thể có ít dữ liệu duy nhất (trong khoảng 3-10 giá trị duy nhất).

print(df_numerical.nunique())

Khi chúng tôi đã xác định được các cột gián điệp, chúng tôi sẽ chuyển chúng từ dữ liệu định lượng sang dữ liệu định tính:

spy_columns = df_numerical[['колонка1', 'колока2', 'колонка3']]#выделяем колонки-шпионы и записываем в отдельную dataframe
df_numerical.drop(labels=['колонка1', 'колока2', 'колонка3'], axis=1, inplace = True)#вырезаем эти колонки из количественных данных
df_categorical.insert(1, 'колонка1', spy_columns['колонка1']) #добавляем первую колонку-шпион в качественные данные
df_categorical.insert(1, 'колонка2', spy_columns['колонка2']) #добавляем вторую колонку-шпион в качественные данные
df_categorical.insert(1, 'колонка3', spy_columns['колонка3']) #добавляем третью колонку-шпион в качественные данные

Cuối cùng, chúng tôi đã tách hoàn toàn dữ liệu định lượng khỏi dữ liệu định tính và bây giờ chúng tôi có thể làm việc với nó một cách chính xác. Điều đầu tiên là phải hiểu nơi chúng ta có các giá trị trống (NaN và trong một số trường hợp 0 ​​sẽ được chấp nhận là giá trị trống).

for i in df_numerical.columns:
    print(i, df[i][df[i]==0].count())

Tại thời điểm này, điều quan trọng là phải hiểu số XNUMX ở cột nào có thể biểu thị các giá trị bị thiếu: điều này có phải do cách thu thập dữ liệu không? Hoặc nó có thể liên quan đến các giá trị dữ liệu? Những câu hỏi này phải được trả lời tùy theo từng trường hợp cụ thể.

Vì vậy, nếu chúng tôi vẫn quyết định rằng chúng tôi có thể thiếu dữ liệu có số XNUMX, chúng tôi nên thay thế số XNUMX bằng NaN để sau này dễ dàng làm việc với dữ liệu bị mất này:

df_numerical[["колонка 1", "колонка 2"]] = df_numerical[["колонка 1", "колонка 2"]].replace(0, nan)

Bây giờ hãy xem chúng ta đang thiếu dữ liệu ở đâu:

sns.heatmap(df_numerical.isnull(),yticklabels=False,cbar=False,cmap='viridis') # Можно также воспользоваться df_numerical.info()

Notepad-cheat sheet để xử lý trước dữ liệu nhanh chóng

Ở đây những giá trị bên trong các cột bị thiếu sẽ được đánh dấu màu vàng. Và bây giờ trò vui bắt đầu - làm thế nào để giải quyết những giá trị này? Tôi có nên xóa các hàng có giá trị hoặc cột này không? Hoặc điền những giá trị trống này bằng một số giá trị khác?

Đây là một sơ đồ gần đúng có thể giúp bạn quyết định về nguyên tắc những gì có thể được thực hiện với các giá trị trống:

Notepad-cheat sheet để xử lý trước dữ liệu nhanh chóng

0. Xóa các cột không cần thiết

df_numerical.drop(labels=["колонка1","колонка2"], axis=1, inplace=True)

1. Số lượng giá trị trống trong cột này có lớn hơn 50% không?

print(df_numerical.isnull().sum() / df_numerical.shape[0] * 100)

df_numerical.drop(labels=["колонка1","колонка2"], axis=1, inplace=True)#Удаляем, если какая-то колонка имеет больше 50 пустых значений

2. Xóa các dòng có giá trị trống

df_numerical.dropna(inplace=True)#Удаляем строчки с пустыми значениями, если потом останется достаточно данных для обучения

3.1. Chèn một giá trị ngẫu nhiên

import random #импортируем random
df_numerical["колонка"].fillna(lambda x: random.choice(df[df[column] != np.nan]["колонка"]), inplace=True) #вставляем рандомные значения в пустые клетки таблицы

3.2. Chèn một giá trị không đổi

from sklearn.impute import SimpleImputer #импортируем SimpleImputer, который поможет вставить значения
imputer = SimpleImputer(strategy='constant', fill_value="<Ваше значение здесь>") #вставляем определенное значение с помощью SimpleImputer
df_numerical[["новая_колонка1",'новая_колонка2','новая_колонка3']] = imputer.fit_transform(df_numerical[['колонка1', 'колонка2', 'колонка3']]) #Применяем это для нашей таблицы
df_numerical.drop(labels = ["колонка1","колонка2","колонка3"], axis = 1, inplace = True) #Убираем колонки со старыми значениями

3.3. Chèn giá trị trung bình hoặc thường xuyên nhất

from sklearn.impute import SimpleImputer #импортируем SimpleImputer, который поможет вставить значения
imputer = SimpleImputer(strategy='mean', missing_values = np.nan) #вместо mean можно также использовать most_frequent
df_numerical[["новая_колонка1",'новая_колонка2','новая_колонка3']] = imputer.fit_transform(df_numerical[['колонка1', 'колонка2', 'колонка3']]) #Применяем это для нашей таблицы
df_numerical.drop(labels = ["колонка1","колонка2","колонка3"], axis = 1, inplace = True) #Убираем колонки со старыми значениями

3.4. Chèn giá trị được tính toán bởi mô hình khác

Đôi khi các giá trị có thể được tính toán bằng mô hình hồi quy sử dụng các mô hình từ thư viện sklearn hoặc các thư viện tương tự khác. Nhóm của chúng tôi sẽ dành một bài viết riêng về cách thực hiện điều này trong tương lai gần.

Vì vậy, hiện tại, phần tường thuật về dữ liệu định lượng sẽ bị gián đoạn vì có nhiều sắc thái khác về cách chuẩn bị và xử lý trước dữ liệu tốt hơn cho các nhiệm vụ khác nhau và những điều cơ bản về dữ liệu định lượng đã được tính đến trong bài viết này, và bây giờ là lúc quay lại dữ liệu định tính, dữ liệu mà chúng tôi đã tách ra vài bước so với dữ liệu định lượng. Bạn có thể thay đổi sổ ghi chép này theo ý muốn, điều chỉnh nó cho phù hợp với các tác vụ khác nhau để quá trình xử lý trước dữ liệu diễn ra rất nhanh chóng!

Dữ liệu định tính

Về cơ bản, đối với dữ liệu định tính, phương pháp mã hóa One-hot-encoding được sử dụng để định dạng nó từ một chuỗi (hoặc đối tượng) thành một số. Trước khi chuyển sang điểm này, hãy sử dụng sơ đồ và mã ở trên để xử lý các giá trị trống.

df_categorical.nunique()

sns.heatmap(df_categorical.isnull(),yticklabels=False,cbar=False,cmap='viridis')

Notepad-cheat sheet để xử lý trước dữ liệu nhanh chóng

0. Xóa các cột không cần thiết

df_categorical.drop(labels=["колонка1","колонка2"], axis=1, inplace=True)

1. Số lượng giá trị trống trong cột này có lớn hơn 50% không?

print(df_categorical.isnull().sum() / df_numerical.shape[0] * 100)

df_categorical.drop(labels=["колонка1","колонка2"], axis=1, inplace=True) #Удаляем, если какая-то колонка 
                                                                          #имеет больше 50% пустых значений

2. Xóa các dòng có giá trị trống

df_categorical.dropna(inplace=True)#Удаляем строчки с пустыми значениями, 
                                   #если потом останется достаточно данных для обучения

3.1. Chèn một giá trị ngẫu nhiên

import random
df_categorical["колонка"].fillna(lambda x: random.choice(df[df[column] != np.nan]["колонка"]), inplace=True)

3.2. Chèn một giá trị không đổi

from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy='constant', fill_value="<Ваше значение здесь>")
df_categorical[["новая_колонка1",'новая_колонка2','новая_колонка3']] = imputer.fit_transform(df_categorical[['колонка1', 'колонка2', 'колонка3']])
df_categorical.drop(labels = ["колонка1","колонка2","колонка3"], axis = 1, inplace = True)

Vì vậy, cuối cùng chúng ta đã xử lý được giá trị rỗng trong dữ liệu định tính. Bây giờ là lúc thực hiện mã hóa một lần trên các giá trị có trong cơ sở dữ liệu của bạn. Phương pháp này thường được sử dụng để đảm bảo rằng thuật toán của bạn có thể học hỏi từ dữ liệu chất lượng cao.

def encode_and_bind(original_dataframe, feature_to_encode):
    dummies = pd.get_dummies(original_dataframe[[feature_to_encode]])
    res = pd.concat([original_dataframe, dummies], axis=1)
    res = res.drop([feature_to_encode], axis=1)
    return(res)

features_to_encode = ["колонка1","колонка2","колонка3"]
for feature in features_to_encode:
    df_categorical = encode_and_bind(df_categorical, feature))

Vậy là cuối cùng chúng ta đã xử lý xong dữ liệu định tính và định lượng riêng biệt - đã đến lúc kết hợp chúng lại

new_df = pd.concat([df_numerical,df_categorical], axis=1)

Sau khi kết hợp các tập dữ liệu lại thành một, cuối cùng chúng ta có thể sử dụng tính năng chuyển đổi dữ liệu bằng MinMaxScaler từ thư viện sklearn. Điều này sẽ làm cho giá trị của chúng tôi nằm trong khoảng từ 0 đến 1, điều này sẽ hữu ích khi đào tạo mô hình trong tương lai.

from sklearn.preprocessing import MinMaxScaler
min_max_scaler = MinMaxScaler()
new_df = min_max_scaler.fit_transform(new_df)

Dữ liệu này hiện đã sẵn sàng cho mọi thứ - mạng thần kinh, thuật toán ML tiêu chuẩn, v.v.!

Trong bài viết này, chúng tôi không tính đến việc làm việc với dữ liệu chuỗi thời gian, vì đối với dữ liệu đó, bạn nên sử dụng các kỹ thuật xử lý hơi khác nhau, tùy thuộc vào nhiệm vụ của bạn. Trong tương lai, nhóm của chúng tôi sẽ dành một bài viết riêng cho chủ đề này và chúng tôi hy vọng rằng nó sẽ có thể mang lại điều gì đó thú vị, mới mẻ và hữu ích cho cuộc sống của bạn, giống như bài viết này.

Nguồn: www.habr.com

Thêm một lời nhận xét