特征理解
《特征工程入门与实践》–特征理解
结构化(有组织)数据:可以分成观察值和特征的数据,一般以表格的形式组织(行是观察值,列是特征)。
非结构化(无组织)数据:作为*流动的实体,不遵循标准组织结构(例如表格)的数据。通常,非结构化数据在我们看来是一团数据,或只有一个特征(列)。
定量数据本质上是数值,应该是衡量某样东西的数量。
定性数据本质上是类别,应该是描述某样东西的性质。
# 导入探索性数据分析所需的包
# 存储表格数据
import pandas as pd
# 数学计算包
import numpy as np
# 流行的数据可视化包
import matplotlib.pyplot as plt
# 另一个流行的数据可视化包
import seaborn as sns
# 允许行内渲染图形
%matplotlib inline
# 流行的数据可视化主题
plt.style.use('fivethirtyeight')
然后导入第一个数据集,探索在旧金山做不同工作的工资。这个数据集可以公开获得,随意使用:
# 导入数据集
# https://data.sfgov.org/City-Management-and-Ethics/Salary-Ranges-
#by-Job-Classification/7h4w-reyq
salary_ranges = pd.read_csv('../data/Salary_Ranges_by_Job_Classification.csv')
# 另一种计算缺失值数量的方法
salary_ranges.isnull().sum()
# 显示描述性统计
salary_ranges.describe()
感兴趣的特征, 最值得注意的特征是一个定量列 Biweekly High Rate(双周最高工资)和一个定性列 Grade(工作种类)。
salary_ranges = salary_ranges[['Biweekly High Rate', 'Grade']]
salary_ranges.head()
# 为了可视化,需要删除美元符号
salary_ranges['Biweekly High Rate'] = salary_ranges['Biweekly High
Rate'].map(lambda value: value.replace('$',''))
# 检查是否已删除干净
salary_ranges.head()
# 将双周最高工资转换为浮点数
salary_ranges['Biweekly High Rate'] = salary_ranges['Biweekly High
Rate'].astype(float)
# 将工作种类转换为字符串
salary_ranges['Grade'] = salary_ranges['Grade'].astype(str)
# 检查转换是否生效
salary_ranges.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1356 entries, 0 to 1355
Data columns (total 2 columns):
Biweekly High Rate 1356 non-null float64
Grade 1356 non-null object
dtypes: float64(1), object(1)
memory usage: 21.3+ KB
数据的4个等级
我们已经可以将数据分为定量和定性的,但是还可以继续分类。数据的4个等级是:
- 定类等级(nominal level)
- 定序等级(ordinal level)
- 定距等级(interval level)
- 定比等级(ratio level)
定类等级
# 对工作种类进行计数
salary_ranges['Grade'].value_counts().head()
00000 61
07450 12
07170 9
07420 9
06870 9
Name: Grade, dtype: int64
# 对工作种类绘制条形图
salary_ranges['Grade'].value_counts().sort_values
(ascending=False).head(20).plot(kind='bar')
# 对工作种类绘制饼图(前5项)
salary_ranges['Grade'].value_counts().sort_values
(ascending=False).head(5).plot(kind='pie')
定序等级
定类等级为我们提供了很多进一步探索的方法。向上一级就到了定序等级。定序等级继承了定类等级的所有属性,而且有重要的附加属性:
定序等级的数据可以自然排序;
这意味着,可以认为列中的某些数据比其他数据更好或更大。
和定类等级一样,定序等级的天然数据属性仍然是类别,即使用数来表示类别也是如此。
可以执行的数学操作
和定类等级相比,定序等级多了一些新的能力。在定序等级,我们可以像定类等级那样进行计数,也可以引入比较和排序。因此,可以使用新的图表了。不仅可以继续使用条形图和饼图,而且因为能排序和比较,所以能计算中位数和百分位数。对于中位数和百分位数,我们可以绘制茎叶图和箱线图。
# 导入数据集
customer = pd.read_csv('../data/2013_SFO_Customer_survey.csv')
customer.shape
(3535, 95)
art_ratings = customer['Q7A_ART']
art_ratings.describe()
count 3535.000000
mean 4.300707
std 1.341445
min 0.000000
25% 3.000000
50% 4.000000
75% 5.000000
max 6.000000
Name: Q7A_ART, dtype: float64
# 只考虑1~5
art_ratings = art_ratings[(art_ratings>=1) & (art_ratings<=5)]
然后将这些值转换为字符串:
# 将值转换为字符串
art_ratings = art_ratings.astype(str)
art_ratings.describe()
count 2656
unique 5
top 4
freq 1066
Name: Q7A_ART, dtype: object
现在定序数据的格式是正确的,可以进行可视化:
# 像定类等级一样用饼图
art_ratings.value_counts().plot(kind='pie')
# 像定类等级一样用条形图
art_ratings.value_counts().plot(kind='bar')
# 定序等级也可以画箱线图
art_ratings.value_counts().plot(kind='box')
定距等级
# 加载数据集
climate = pd.read_csv('../data/GlobalLandTemperaturesByCity.csv')
climate.head()
# 移除缺失值
climate.dropna(axis=0, inplace=True)
climate.head() # 检查是否已移除干净
climate.isnull().sum()
dt 0
AverageTemperature 0
AverageTemperatureUncertainty 0
City 0
Country 0
Latitude 0
Longitude 0
dtype: int64
# 没有问题
# 显示独特值的数量
climate['AverageTemperature'].nunique()
111994
climate['AverageTemperature'].hist()
# 将dt栏转换为日期,取年份
climate['dt'] = pd.to_datetime(climate['dt'])
climate['year'] = climate['dt'].map(lambda value: value.year)
# 只看美国
climate_sub_us = climate.loc[climate['Country'] == 'United States']
climate_sub_us['century'] = climate_sub_us['year'].map(lambda x: int(x/100+1))
# 1983变成20
# 1750变成18
climate_sub_us['AverageTemperature'].hist(by=climate_sub_us['century'],
sharex=True, sharey=True,
figsize=(10, 10),
bins=20)
century_changes =
climate_sub_us.groupby('century')['AverageTemperature'].mean()
century_changes
century
18 12.073243
19 13.662870
20 14.386622
21 15.197692
Name: AverageTemperature, dtype: float64
# 21世纪的平均温度减去18世纪的平均温度
century_changes[21] - century_changes[18]
# 均值是21世纪的月平均温度减去18世纪的月平均温度
3.124449115460754
在定距等级绘制两列数
x = climate_sub_us['year']
y = climate_sub_us['AverageTemperature']
fig, ax = plt.subplots(figsize=(10,5))
ax.scatter(x, y)
plt.show()
# 用groupby清除美国气温的噪声
climate_sub_us.groupby('year').mean()['AverageTemperature'].plot()
# 用滑动均值平滑图像
climate_sub_us.groupby('year').mean()['AverageTemperature'].rolling(10).mean().plot()
定比等级
# 哪个工作种类的工资最高
# 每个工作种类的平均工资是多少
fig = plt.figure(figsize=(15,5))
ax = fig.gca()
salary_ranges.groupby('Grade')[['Biweekly High Rate']].mean().sort_values(
'Biweekly High Rate', ascending=False).head(20).plot.bar(stacked=False, ax=ax,
color='darkorange')
ax.set_title('Top 20 Grade by Mean Biweekly High Rate')
# 哪个工作种类的工资最低
fig = plt.figure(figsize=(15,5))
ax = fig.gca()
salary_ranges.groupby('Grade')[['Biweekly High
Rate']].mean().sort_values('Biweekly High Rate',
ascending=False).tail(20).plot.bar(stacked=False, ax=ax,
color='darkorange')
ax.set_title('Bottom 20 Grade by Mean Biweekly High Rate')
因为金钱处于定比等级,所以可以计算最高工资和最低工资的比值:
sorted_df = salary_ranges.groupby('Grade')[['Biweekly High
Rate']].mean().sort_values(
'Biweekly High Rate', ascending=False)
sorted_df.iloc[0][0] / sorted_df.iloc[-1][0]
13.931919540229886