10.3.2 数据集预处理
在本项目中,我们将使用美国消费者金融保护局(CFPB)的用户投诉数据集,在被投诉部门做出回应后,会在消费者投诉数据库中发布这些数据。
(1)加载投诉数据集main.csv,然后删除了名为 'Unnamed: 0' 的列。具体实现代码如下所示。
df = pd.read_csv('input/complaintsfull/main.csv',low_memory=False)
df = df.drop(['Unnamed: 0'],axis=1)
执行后输出:
CPU times: user 22.3 s, sys: 3.15 s, total: 25.5 s
Wall time: 36.9 s
快速浏览这个数据集,可以看到在这个自然语言处理(NLP)问题中对我们感兴趣的特征有产品(金融产品类型)、子产品(产品的更详细子集)、问题(问题是什么)、子问题(问题的更详细子集)。
(2)使用了库missingno中的函数matrix来可视化数据框 df 中的缺失数据情况,具体实现代码如下所示。
import missingno as ms
ms.matrix(df)
执行效果如图10-22所示,这种可视化矩阵可以帮助我们快速识别数据集中的缺失值。
图10-22 数据集中的缺失值可视化效果
(3)打印数据集中的特征(列名),以便查看数据集的列标题。具体实现代码如下所示。
print('Dataset Features')
df.columns
通过运行这段代码,可以查看数据集中包含的各个特征或列的名称,这有助于你了解数据的结构和内容。执行后会输出:
Index(['Date received', 'Product', 'Sub-product', 'Issue', 'Sub-issue',
'Consumer complaint narrative', 'Company public response', 'Company',
'State', 'ZIP code', 'Tags', 'Consumer consent provided?',
'Submitted via', 'Date sent to company', 'Company response to consumer',
'Timely response?', 'Consumer disputed?', 'Complaint ID', 'Year',
'Month', 'Day', 'DoW'],
dtype='object')
注意:df.columns 返回一个包含数据集列名的 pandas Series 对象,你可以根据需要将其进一步处理或显示。
(4)定义一个名为 object_to_datetime_features 的函数,该函数将数据框中的一个列从对象类型转换为 datetime64[ns] 类型,并创建了一些新的日期相关特征列,包括年份、月份、日期和星期几。然后你将该函数应用于数据框 df 中的名为 'Date received' 的列,以便将该列的数据类型从对象转换为日期时间类型,并创建新的日期相关特征列。最后,你打印了数据框的列名,以查看是否成功添加了新的特征列。具体实现代码如下所示。
def object_to_datetime_features(df,column):
df[column] = df[column].astype('datetime64[ns]')
df['Year'] = df[column].dt.year
df['Month'] = df[column].dt.month
df['Day'] = df[column].dt.day
df['DoW'] = df[column].dt.dayofweek
df['DoW'] = df['DoW'].replace({0:'Monday',1:'Tuesday',2:'Wednesday',
3:'Thursday',4:'Friday',5:'Saturday',6:'Sunday'})
return df
df = object_to_datetime_features(df,'Date received')
df.columns
执行后会输出:
Index(['Date received', 'Product', 'Sub-product', 'Issue', 'Sub-issue',
'Consumer complaint narrative', 'Company public response', 'Company',
'State', 'ZIP code', 'Tags', 'Consumer consent provided?',
'Submitted via', 'Date sent to company', 'Company response to consumer',
'Timely response?', 'Consumer disputed?', 'Complaint ID', 'Year',
'Month', 'Day', 'DoW'],
dtype='object')
(5)定义函数normalise_column_names,用于将数据框中的列名(特征名)规范化为小写字母形式。具体来说,它将列名的每个字符都转换为小写,并将结果分配回数据框的列名。然后,将该函数应用于数据框 df 中,以便将所有列名都规范化为小写字母形式。具体实现代码如下所示。
def normalise_column_names(df):
normalised_features = [i.lower() for i in list(df.columns)]
df.columns = normalised_features
return df
df = normalise_column_names(df)
这种规范化通常有助于减少数据处理中的不一致性,并使列名更易于使用和引用。
(6)定义函数show_subset_names,功能是返回指定列中唯一子集的名称。该函数接受一个数据框 df 和一个列名 column 作为参数,使用 .value_counts().index获取该列中唯一值的索引,这些唯一值代表了子集的名称。然后,将该函数应用于数据框 df 中的 'product' 列,以查看该列中不同产品的唯一名称。这对于了解数据集中存在哪些产品类别非常有用。具体实现代码如下所示。
def show_subset_names(df,column):
return df[column].value_counts().index
show_subset_names(df,'product')
执行后会输出:
Index(['Credit reporting, credit repair services, or other personal consumer reports',
'Debt collection', 'Mortgage', 'Credit card or prepaid card',
'Checking or savings account', 'Student loan', 'Credit reporting',
'Money transfer, virtual currency, or money service',
'Vehicle loan or lease', 'Credit card', 'Bank account or service',
'Payday loan, title loan, or personal loan', 'Consumer Loan',
'Payday loan', 'Money transfers', 'Prepaid card',
'Other financial service', 'Virtual currency'],
dtype='object')
(7)定义函数normalise_subset_names,功能是是规范化指定列中唯一子集的名称。然后,将该函数应用于数据框 df 中的 'product' 列,以规范化该列中的产品名称,并使用 show_subset_names 函数查看规范化后的产品名称。具体实现代码如下所示。
def normalise_subset_names(df,column):
subset_names = list(df[column].value_counts().index)
norm_subset_names = [i.lower() for i in subset_names]
dict_replace = dict(zip(subset_names,norm_subset_names))
df[column] = df[column].replace(dict_replace)
return df
df = normalise_subset_names(df,'product')
show_subset_names(df,'product')
执行后输出:
Index(['credit reporting, credit repair services, or other personal consumer reports',
'debt collection', 'mortgage', 'credit card or prepaid card',
'checking or savings account', 'student loan', 'credit reporting',
'money transfer, virtual currency, or money service',
'vehicle loan or lease', 'credit card', 'bank account or service',
'payday loan, title loan, or personal loan', 'consumer loan',
'payday loan', 'money transfers', 'prepaid card',
'other financial service',
(8)使用函数keep_subset根据指定的产品子集名称列表 lst_keep 来保留了数据框 df 中的特定产品类别,然后使用value_counts()方法查看保留后的数据框中每个产品类别的计数。具体实现代码如下所示。
lst_keep = ['credit reporting', 'debt collection', 'mortgage', 'credit card',
'bank account or service', 'consumer Loan', 'student loan',
'payday loan', 'prepaid card', 'money transfers',
'other financial service', 'virtual currency']
df = keep_subset(df,'product',lst_keep)
# sdf = remove_subset(df,'product',lst_remove)
df['product'].value_counts()
执行后输出:
debt collection 195373
mortgage 99141
student loan 33606
credit reporting 31587
credit card 18838
bank account or service 14885
payday loan 1746
money transfers 1497
prepaid card 1450
other financial service 292
virtual currency 16
Name: product, dtype: int64
(9)查看数据框 df 中 'year' 列中每个年份的计数,如果 'year' 列包含表示年份的数据,可以使用value_counts() 方法来获取每个年份的计数。具体实现代码如下所示。
df['year'].value_counts()
执行后输出:
2016 73146
2017 59087
2015 51779
2021 50757
2022 42867
2018 41708
2020 40801
2019 38286
Name: year, dtype: int64
(10)对数据框 df 按 'product' 列进行分组,然后对每个产品类别计算了 'day' 列的计数。接着,将结果转换为一个 DataFrame,并按 'day' 列的值进行降序排序。最后,使用style.bar() 方法来创建带有条形图的样式。具体实现代码如下所示。
ldf = df.groupby('product').count()['day'].to_frame().sort_values(ascending=False,by='day')
ldf.style\
.bar(align='mid',
color=['#d65f5f','#F1A424'])
执行效果如图10-23所示。
图10-23 排序结果效果
(11)从数据框 df 中筛选出了 'year' 列包含在列表 [2015, 2016, 2017] 中的行,然后打印了最终筛选后数据框的形状(行数和列数)。具体实现代码如下所示。
df = df[df['year'].isin([2015,2016,2017])]
print(f'final shape: {df.shape}')
执行后输出:
final shape: (184012, 22)