数据分析高级指南(三)
原文:
zh.annas-archive.org/md5/33fdac647f302560c3fa02dc8d0db0c8译者:飞龙
第十二章:Python 中的数据操作和可视化
在第八章中,你学习如何在数据操作和可视化方面使用tidyverse套件。在这里,我们将在 Python 中演示类似的技术,应用于相同的star数据集。特别是,我们将使用pandas和seaborn分别进行数据操作和可视化。这不是关于这些模块或 Python 在数据分析中的全部功能的详尽指南。相反,这足以让你自己探索。
尽可能地,我会模仿我们在第八章中所做的步骤,并执行相同的操作。因为熟悉这些操作,我会更专注于如何在 Python 中执行数据操作和可视化,而不是为什么这样做。让我们加载必要的模块,并开始使用star。第三个模块matplotlib对你来说是新的,将用于辅助我们在seaborn中的工作。它已经随 Anaconda 安装。具体来说,我们将使用pyplot子模块,并将其别名为plt。
In [1]: import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
star = pd.read_excel('datasets/star/star.xlsx')
star.head()
Out[1]:
tmathssk treadssk classk totexpk sex freelunk race \
0 473 447 small.class 7 girl no white
1 536 450 small.class 21 girl no black
2 463 439 regular.with.aide 0 boy yes black
3 559 448 regular 16 boy no white
4 489 447 small.class 5 boy yes white
schidkn
0 63
1 20
2 19
3 69
4 79
列操作
在第十一章中,你学习到pandas将尝试将一维数据结构转换为 Series。当选择列时,这个看似微不足道的点将变得非常重要。让我们看一个例子:假设我们只想保留 DataFrame 中的tmathssk列。我们可以使用熟悉的单括号表示法来做到这一点,但从技术上讲,这会导致一个 Series,而不是 DataFrame:
In [2]: math_scores = star['tmathssk']
type(math_scores)
Out[2]: pandas.core.series.Series
如果我们不能确定是否希望math_scores保持为一维结构,最好将其保留为 DataFrame。为此,我们可以使用两组方括号而不是一组:
In [3]: math_scores = star[['tmathssk']]
type(math_scores)
Out[3]: pandas.core.frame.DataFrame
按照这个模式,我们可以在star中仅保留所需的列。我将使用columns属性来确认。
In [4]: star = star[['tmathssk','treadssk','classk','totexpk','schidkn']]
star.columns
Out[4]: Index(['tmathssk', 'treadssk', 'classk',
'totexpk', 'schidkn'], dtype='object')
要删除特定的列,请使用drop()方法。drop()可以用于删除列或行,所以我们需要通过使用axis参数来指定。在pandas中,行是轴0,列是轴1,正如图 12-1 所示。
图 12-1。一个pandas DataFrame 的轴
这里是如何删除schidkn列的方法:
In [5]: star = star.drop('schidkn', axis=1)
star.columns
Out[5]: Index(['tmathssk', 'treadssk',
'classk', 'totexpk'], dtype='object')
现在让我们来看看如何从 DataFrame 中派生新的列。我们可以使用方括号表示法来做到这一点——这一次,我确实希望结果是一个 Series,因为 DataFrame 的每一列实际上都是一个 Series(就像 R 数据框的每一列实际上都是一个向量一样)。在这里,我将计算数学和阅读成绩的综合:
In [6]: star['new_column'] = star['tmathssk'] + star['treadssk']
star.head()
Out[6]:
tmathssk treadssk classk totexpk new_column
0 473 447 small.class 7 920
1 536 450 small.class 21 986
2 463 439 regular.with.aide 0 902
3 559 448 regular 16 1007
4 489 447 small.class 5 936
再次,new_column不是一个非常描述性的变量名。让我们使用rename()函数来修复它。我们将使用columns参数,并以你可能不熟悉的格式传递数据:
In [7]: star = star.rename(columns = {'new_column':'ttl_score'})
star.columns
Out[7]: Index(['tmathssk', 'treadssk', 'classk', 'totexpk', 'ttl_score'],
dtype='object')
上一个示例中使用的花括号表示法是 Python 的 字典。字典是 键-值 对的集合,每个元素的键和值由冒号分隔。这是 Python 的核心数据结构之一,是你继续学习该语言时要了解的内容。
按行进行操作
现在让我们转向按行常见的操作。我们将从排序开始,在 pandas 中可以使用 sort_values() 方法完成。我们将按照各列的指定顺序传递给 by 参数来排序:
In [8]: star.sort_values(by=['classk', 'tmathssk']).head()
Out[8]:
tmathssk treadssk classk totexpk ttl_score
309 320 360 regular 6 680
1470 320 315 regular 3 635
2326 339 388 regular 6 727
2820 354 398 regular 6 752
4925 354 391 regular 8 745
默认情况下,所有列都按升序排序。要修改这一点,我们可以包含另一个参数 ascending,其中包含 True/False 标志的列表。让我们按照班级大小(classk)升序和数学分数(treadssk)降序来排序 star。因为我们没有将此输出重新分配给 star,所以这种排序不会永久影响数据集。
In [9]: # Sort by class size ascending and math score descending
star.sort_values(by=['classk', 'tmathssk'],
ascending=[True, False]).head()
Out[9]:
tmathssk treadssk classk totexpk ttl_score
724 626 474 regular 15 1100
1466 626 554 regular 11 1180
1634 626 580 regular 15 1206
2476 626 538 regular 20 1164
2495 626 522 regular 7 1148
要筛选 DataFrame,我们首先使用条件逻辑创建一个 Series,其中包含每行是否符合某些条件的 True/False 标志。然后,我们仅保留 DataFrame 中 Series 中标记为 True 的记录。例如,让我们仅保留 classk 等于 small.class 的记录。
In [10]: small_class = star['classk'] == 'small.class'
small_class.head()
Out[10]:
0 True
1 True
2 False
3 False
4 True
Name: classk, dtype: bool
现在,我们可以使用括号过滤此结果的 Series。我们可以使用 shape 属性确认新 DataFrame 的行数和列数:
In [11]: star_filtered = star[small_class]
star_filtered.shape
Out[11]: (1733, 5)
star_filtered 将包含比 star 更少的行,但列数相同:
In [12]: star.shape
Out[12]: (5748, 5)
让我们再试一次:找到 treadssk 至少为 500 的记录:
In [13]: star_filtered = star[star['treadssk'] >= 500]
star_filtered.shape
Out[13]: (233, 5)
还可以使用 and/or 语句根据多个条件进行过滤。就像在 R 中一样,& 和 | 分别表示 "和" 和 "或"。让我们将前面的两个条件放入括号中,并使用 & 将它们连接到一个语句中:
In [14]: # Find all records with reading score at least 500 and in small class
star_filtered = star[(star['treadssk'] >= 500) &
(star['classk'] == 'small.class')]
star_filtered.shape
Out[14]: (84, 5)
聚合和连接数据
要在 DataFrame 中对观察结果进行分组,我们将使用 groupby() 方法。如果打印 star_grouped,你会看到它是一个 DataFrameGroupBy 对象:
In [15]: star_grouped = star.groupby('classk')
star_grouped
Out[15]: <pandas.core.groupby.generic.DataFrameGroupBy
object at 0x000001EFD8DFF388>
现在我们可以选择其他字段来对这个分组的 DataFrame 进行聚合。Table 12-1 列出了一些常见的聚合方法。
表 12-1. pandas 中有用的聚合函数
| 方法 | 聚合类型 |
|---|---|
sum() | 总和 |
count() | 计数值 |
mean() | 平均值 |
max() | 最高值 |
min() | 最小值 |
std() | 标准差 |
以下给出了每个班级大小的平均数学分数:
In [16]: star_grouped[['tmathssk']].mean()
Out[16]:
tmathssk
classk
regular 483.261000
regular.with.aide 483.009926
small.class 491.470283
现在我们将找到每年教师经验的最高总分。因为这将返回相当多的行,我将包含 head() 方法以仅获取一些行。将多个方法添加到同一命令的这种做法称为方法 链式调用:
In [17]: star.groupby('totexpk')[['ttl_score']].max().head()
Out[17]:
ttl_score
totexpk
0 1171
1 1133
2 1091
3 1203
4 1229
第八章回顾了 Excel 的VLOOKUP()和左外连接之间的相似性和差异。我将重新读入star和districts的最新副本;让我们使用pandas来合并这些数据集。我们将使用merge()方法将school-districts中的数据“查找”到star中。通过将how参数设置为left,我们将指定左外连接,这是最接近VLOOKUP()的连接类型:
In [18]: star = pd.read_excel('datasets/star/star.xlsx')
districts = pd.read_csv('datasets/star/districts.csv')
star.merge(districts, how='left').head()
Out[18]:
tmathssk treadssk classk totexpk sex freelunk race \
0 473 447 small.class 7 girl no white
1 536 450 small.class 21 girl no black
2 463 439 regular.with.aide 0 boy yes black
3 559 448 regular 16 boy no white
4 489 447 small.class 5 boy yes white
schidkn school_name county
0 63 Ridgeville New Liberty
1 20 South Heights Selmont
2 19 Bunnlevel Sattley
3 69 Hokah Gallipolis
4 79 Lake Mathews Sugar Mountain
Python 像 R 一样对数据连接非常直观:它默认使用schidkn进行合并,并同时引入school_name和county。
数据重塑
让我们来看看如何在 Python 中扩展和延长数据集,再次使用pandas。首先,我们可以使用melt()函数将tmathssk和treadssk合并到一列中。为此,我将指定要使用frame参数操作的 DataFrame,使用id_vars作为唯一标识符的变量,并使用value_vars将变量融合为单列。我还将指定如何命名生成的值和标签变量,分别为value_name和var_name:
In [19]: star_pivot = pd.melt(frame=star, id_vars = 'schidkn',
value_vars=['tmathssk', 'treadssk'], value_name='score',
var_name='test_type')
star_pivot.head()
Out[19]:
schidkn test_type score
0 63 tmathssk 473
1 20 tmathssk 536
2 19 tmathssk 463
3 69 tmathssk 559
4 79 tmathssk 489
如何将tmathssk和treadssk重命名为math和reading?为此,我将使用一个 Python 字典来设置一个名为mapping的对象,它类似于一个“查找表”以重新编码这些值。我将把它传递给map()方法来重新编码test_type。我还将使用unique()方法确认test_type现在仅包含math和reading:
In [20]: # Rename records in `test_type`
mapping = {'tmathssk':'math','treadssk':'reading'}
star_pivot['test_type'] = star_pivot['test_type'].map(mapping)
# Find unique values in test_type
star_pivot['test_type'].unique()
Out[20]: array(['math', 'reading'], dtype=object)
要将star_pivot扩展回单独的math和reading列,我将使用pivot_table()方法。首先,我将指定要使用index参数索引的变量,然后使用columns和values参数指定标签和值来自哪些变量:
在pandas中,可以设置唯一的索引列;默认情况下,pivot_table()将设置index参数中包含的任何变量。为了覆盖这一点,我将使用reset_index()方法。要了解更多关于pandas中自定义索引以及其他无数的数据操作和分析技术,请参阅《Python for Data Analysis》(O'Reilly 出版社第 2 版)作者 Wes McKinney 的书籍链接。
In [21]: star_pivot.pivot_table(index='schidkn',
columns='test_type', values='score').reset_index()
Out[21]:
test_type schidkn math reading
0 1 492.272727 443.848485
1 2 450.576923 407.153846
2 3 491.452632 441.000000
3 4 467.689655 421.620690
4 5 460.084746 427.593220
.. ... ... ...
74 75 504.329268 440.036585
75 76 490.260417 431.666667
76 78 468.457627 417.983051
77 79 490.500000 434.451613
78 80 490.037037 442.537037
[79 rows x 3 columns]
数据可视化
现在让我们简要介绍一下 Python 中的数据可视化,特别是使用seaborn包。seaborn在统计分析和pandas数据框架中表现特别出色,因此在这里是一个很好的选择。类似于pandas是建立在numpy之上,seaborn利用了另一个流行的 Python 绘图包matplotlib的功能。
seaborn包括许多函数来构建不同类型的图表。我们将修改这些函数中的参数,以指定要绘制的数据集、沿 x 轴和 y 轴的变量、要使用的颜色等。我们首先通过使用countplot()函数来可视化每个classk水平的观察计数。
我们的数据集是star,我们将使用data参数指定。要将classk的水平放置在 x 轴上,我们将使用x参数。这导致了图 12-2 中所示的计数图:
In [22]: sns.countplot(x='classk', data=star)
图 12-2. 计数图
现在对于treadssk的直方图,我们将使用displot()函数。同样,我们将指定x和data。图 12-3 展示了结果:
In [23]: sns.displot(x='treadssk', data=star)
图 12-3. 直方图
seaborn函数包括许多可选参数,用于自定义图表的外观。例如,让我们将箱数更改为 25 并将绘图颜色更改为粉红色。这将产生图 12-4:
In [24]: sns.displot(x='treadssk', data=star, bins=25, color='pink')
图 12-4. 自定义直方图
要制作箱线图,使用boxplot()函数,如图 12-5 所示:
In [25]: sns.boxplot(x='treadssk', data=star)
到目前为止,在所有这些情况下,我们都可以通过将感兴趣的变量包含在y参数中来“翻转”图表。让我们尝试使用我们的箱线图进行演示,我们将得到图 12-6 中显示的输出:
In [26]: sns.boxplot(y='treadssk', data=star)
图 12-5. 箱线图
图 12-6. “翻转”的箱线图
要为每个班级大小水平制作箱线图,我们将在classk的 x 轴上包含一个额外的参数,这样就得到了图 12-7 中所示的按组的箱线图:
In [27]: sns.boxplot(x='classk', y='treadssk', data=star)
图 12-7. 按组的箱线图
现在让我们使用scatterplot()函数在 x 轴上绘制tmathssk与 y 轴上的treadssk之间的关系。图 12-8 是结果:
In [28]: sns.scatterplot(x='tmathssk', y='treadssk', data=star)
图 12-8. 散点图
假设我们想要与外部观众分享这个图表,他们可能不熟悉treadssk和tmathssk是什么。我们可以通过从matplotlib.pyplot中借用功能向该图表添加更多有用的标签。我们将与之前相同地运行scatterplot()函数,但这次我们还将调用pyplot中的函数来添加自定义的 x 和 y 轴标签,以及图表标题。这导致了图 12-9 中显示的带有标签的散点图:
In [29]: sns.scatterplot(x='tmathssk', y='treadssk', data=star)
plt.xlabel('Math score')
plt.ylabel('Reading score')
plt.title('Math score versus reading score')
图 12-9. 带有自定义轴标签和标题的散点图
seaborn包括许多功能,用于构建视觉上吸引人的数据可视化。要了解更多,请查看官方文档。
结论
pandas和seaborn能做的远不止这些,但这已足以让你开始真正的任务:探索和测试数据中的关系。这将是第十三章的重点。
练习
书籍存储库的datasets子文件夹census中有两个文件,census.csv和census-divisions.csv。将这些文件读入 Python 并执行以下操作:
-
按地区升序、分区升序和人口降序对数据进行排序(你需要合并数据集才能做到这一点)。将结果写入 Excel 工作表。
-
从合并的数据集中删除邮政编码字段。
-
创建一个名为density的新列,该列是人口除以陆地面积的计算结果。
-
可视化 2015 年所有观察中陆地面积和人口之间的关系。
-
找出每个地区在 2015 年的总人口。
-
创建一个包含州名和人口的表,每年 2010 年至 2015 年的人口分别保留在一个单独的列中。
第十三章:项目实战:Python 数据分析
在 第八章 结尾,你扩展了对 R 的学习,以探索和测试 mpg 数据集中的关系。在本章中,我们将使用 Python 进行相同的工作。我们在 Excel 和 R 中进行了相同的工作,所以我将更专注于如何在 Python 中进行分析,而不是为什么要进行分析。
要开始,请调用所有必要的模块。其中一些是新的:从 scipy 中,我们将导入 stats 子模块。为了告诉 Python 要查找哪个模块,我们将使用 from 关键字,然后使用 import 关键字来选择一个子模块。正如其名,我们将使用 scipy 的 stats 子模块来进行统计分析。我们还将使用一个称为 sklearn 或 scikit-learn 的新包,在训练/测试拆分上验证我们的模型。这个包已经成为机器学习的主要资源,并且与 Anaconda 一起安装。
In [1]: import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from scipy import stats
from sklearn import linear_model
from sklearn import model_selection
from sklearn import metrics
使用 read_csv() 的 usecols 参数,我们可以指定读入 DataFrame 的列:
In [2]: mpg = pd.read_csv('datasets/mpg/mpg.csv',usecols=
['mpg','weight','horsepower','origin','cylinders'])
mpg.head()
Out[2]:
mpg cylinders horsepower weight origin
0 18.0 8 130 3504 USA
1 15.0 8 165 3693 USA
2 18.0 8 150 3436 USA
3 16.0 8 150 3433 USA
4 17.0 8 140 3449 USA
探索性数据分析
让我们从描述统计开始:
In[3]: mpg.describe()
Out[3]:
mpg cylinders horsepower weight
count 392.000000 392.000000 392.000000 392.000000
mean 23.445918 5.471939 104.469388 2977.584184
std 7.805007 1.705783 38.491160 849.402560
min 9.000000 3.000000 46.000000 1613.000000
25% 17.000000 4.000000 75.000000 2225.250000
50% 22.750000 4.000000 93.500000 2803.500000
75% 29.000000 8.000000 126.000000 3614.750000
max 46.600000 8.000000 230.000000 5140.000000
因为 origin 是一个分类变量,默认情况下它不会显示为 describe() 的一部分。让我们改为用频率表探索这个变量。这可以在 pandas 中用 crosstab() 函数来实现。首先,我们将指定将数据放在索引上的内容:origin。通过将 columns 参数设置为 count,我们将得到每个水平的计数:
In [4]: pd.crosstab(index=mpg['origin'], columns='count')
Out[4]:
col_0 count
origin
Asia 79
Europe 68
USA 245
要制作双向频率表,我们可以将 columns 设置为另一个分类变量,如 cylinders:
In [5]: pd.crosstab(index=mpg['origin'], columns=mpg['cylinders'])
Out[5]:
cylinders 3 4 5 6 8
origin
Asia 4 69 0 6 0
Europe 0 61 3 4 0
USA 0 69 0 73 103
接下来,让我们按 origin 水平检索 mpg 的描述统计信息。我将通过链接两种方法,然后子集化结果来完成这项工作:
In[6]: mpg.groupby('origin').describe()['mpg']
Out[6]:
count mean std min 25% 50% 75% max
origin
Asia 79.0 30.450633 6.090048 18.0 25.70 31.6 34.050 46.6
Europe 68.0 27.602941 6.580182 16.2 23.75 26.0 30.125 44.3
USA 245.0 20.033469 6.440384 9.0 15.00 18.5 24.000 39.0
我们还可以像 图 13-1 那样可视化 mpg 的整体分布:
In[7]: sns.displot(data=mpg, x='mpg')
图 13-1. mpg 的直方图
现在让我们制作一个箱线图,如 图 13-2,比较每个 origin 水平上 mpg 的分布:
In[8]: sns.boxplot(x='origin', y='mpg', data=mpg, color='pink')
图 13-2. 按 origin 分组的 mpg 箱线图
或者,我们可以将 displot() 的 col 参数设置为 origin 来创建分面直方图,例如 图 13-3:
In[9]: sns.displot(data=mpg, x="mpg", col="origin")
图 13-3. 按 origin 分组的分面直方图
假设检验
让我们再次测试美国和欧洲汽车之间的里程差异。为了便于分析,我们将每个组中的观测分割成它们自己的数据框。
In[10]: usa_cars = mpg[mpg['origin']=='USA']
europe_cars = mpg[mpg['origin']=='Europe']
独立样本 t 检验
现在我们可以使用 scipy.stats 中的 ttest_ind() 函数进行 t 检验。这个函数期望接收两个 numpy 数组作为参数;pandas 的 Series 也可以使用:
In[11]: stats.ttest_ind(usa_cars['mpg'], europe_cars['mpg'])
Out[11]: Ttest_indResult(statistic=-8.534455914399228,
pvalue=6.306531719750568e-16)
不幸的是,这里的输出相当有限:虽然包括了 p 值,但未包括置信区间。要获得更多输出的 t 检验结果,请查看researchpy模块。
现在我们来分析我们的连续变量。我们将从相关矩阵开始。我们可以使用pandas中的corr()方法,只包括相关变量:
In[12]: mpg[['mpg','horsepower','weight']].corr()
Out[12]:
mpg horsepower weight
mpg 1.000000 -0.778427 -0.832244
horsepower -0.778427 1.000000 0.864538
weight -0.832244 0.864538 1.000000
接下来,让我们用散点图可视化weight和mpg之间的关系,如图 13-4 所示:
In[13]: sns.scatterplot(x='weight', y='mpg', data=mpg)
plt.title('Relationship between weight and mileage')
图 13-4. mpg按weight的散点图
或者,我们可以使用seaborn的pairplot()函数在数据集的所有变量对上生成散点图。对角线上包括每个变量的直方图,如图 13-5 所示:
In[14]: sns.pairplot(mpg[['mpg','horsepower','weight']])
图 13-5. mpg、horsepower和weight的 Pairplot
线性回归
现在是进行线性回归的时候了。为此,我们将使用scipy中的linregress()函数,该函数同样适用于两个numpy数组或pandas Series。我们将使用x和y参数指定哪个变量是独立变量和依赖变量:
In[15]: # Linear regression of weight on mpg
stats.linregress(x=mpg['weight'], y=mpg['mpg'])
Out[15]: LinregressResult(slope=-0.007647342535779578,
intercept=46.21652454901758, rvalue=-0.8322442148315754,
pvalue=6.015296051435726e-102, stderr=0.0002579632782734318)
同样地,您会发现您习惯于看到的一些输出在这里是缺失的。请注意: 这里包含的rvalue是相关系数,而不是 R 平方。要获得更丰富的线性回归输出,请查看statsmodels模块。
最后但同样重要,让我们在散点图上叠加回归线。seaborn有一个专门的函数来实现这一点:regplot()。与往常一样,我们将指定我们的独立和依赖变量,以及数据的来源。这将产生图 13-6:
In[16]: # Fit regression line to scatterplot
sns.regplot(x="weight", y="mpg", data=mpg)
plt.xlabel('Weight (lbs)')
plt.ylabel('Mileage (mpg)')
plt.title('Relationship between weight and mileage')
图 13-6. mpg按weight的散点图与拟合回归线
训练/测试拆分与验证
在第九章结束时,您学习了如何在构建 R 中的线性回归模型时应用训练/测试拆分。
我们将使用train_test_split()函数将数据集分为四个 DataFrame:不仅包括训练和测试数据,还包括独立和依赖变量。我们将先传入包含独立变量的 DataFrame,然后是包含依赖变量的 DataFrame。使用random_state参数,我们会为随机数生成器设置种子,以确保本示例的结果保持一致:
In[17]: X_train, X_test, y_train, y_test =
model_selection.train_test_split(mpg[['weight']], mpg[['mpg']],
random_state=1234)
默认情况下,数据以 75/25 的比例分割为训练和测试子集。
In[18]: y_train.shape
Out[18]: (294, 1)
In[19]: y_test.shape
Out[19]: (98, 1)
现在,让我们将模型拟合到训练数据上。首先,我们将使用LinearRegression()指定线性模型,然后使用regr.fit()训练模型。要获取测试数据集的预测值,我们可以使用predict()方法。这将得到一个numpy数组,而不是pandas DataFrame,因此head()方法不能用来打印前几行。不过,我们可以对其进行切片操作:
In[20]: # Create linear regression object
regr = linear_model.LinearRegression()
# Train the model using the training sets
regr.fit(X_train, y_train)
# Make predictions using the testing set
y_pred = regr.predict(X_test)
# Print first five observations
y_pred[:5]
Out[20]: array([[14.86634263],
[23.48793632],
[26.2781699 ],
[27.69989655],
[29.05319785]])
coef_属性返回了我们测试模型的系数:
In[21]: regr.coef_
Out[21]: array([[-0.00760282]])
要获取关于模型的更多信息,如系数的 p 值或 R 平方,请尝试使用statsmodels包进行拟合。
目前,我们将评估模型在测试数据上的表现,这次使用sklearn的metrics子模块。我们将实际值和预测值传递给r2_score()和mean_squared_error()函数,分别返回 R 平方和 RMSE。
In[22]: metrics.r2_score(y_test, y_pred)
Out[22]: 0.6811923996681357
In[23]: metrics.mean_squared_error(y_test, y_pred)
Out[23]: 21.63348076436662
结论
这一章节的常规警告同样适用:我们只是触及了对这个或任何其他数据集可能进行的分析的表面。但我希望你感觉在使用 Python 处理数据方面已经步入佳境。
练习
再次查看ais数据集,这次使用 Python。从书籍仓库中读取 Excel 工作簿,并完成以下操作。现在你应该对这个分析已经非常熟悉了。
-
通过性别(sex)可视化红细胞计数(rcc)的分布。
-
两组性别之间的红细胞计数是否存在显著差异?
-
在该数据集中生成相关变量的相关矩阵。
-
可视化身高(ht)和体重(wt)之间的关系。
-
将wt回归到ht上。找出拟合回归线的方程。是否存在显著关系?
-
将回归模型分割成训练集和测试集。测试模型的 R 平方和 RMSE 是多少?
第十四章:结论与下一步
在前言中,我表明了以下学习目标:
在本书的最后,您应该能够使用编程语言进行探索性数据分析和假设检验。
我真诚地希望您觉得这个目标已经实现,并且有信心进一步深入分析的领域。为了结束您的分析之旅的这一段,我想分享一些主题,帮助您完善和扩展您现在所知道的内容。
进一步的技术栈
第五章涵盖了数据分析中使用的四大类软件应用程序:电子表格、编程语言、数据库和 BI 工具。由于我们专注于统计学基础的分析元素,我们强调了技术栈的前两层。回顾该章节,以了解其他层次如何衔接以及关于它们的学习内容。
研究设计与商业实验
您在第三章中学到,良好的数据分析只能从良好的数据收集开始:正如俗语所说,“垃圾进,垃圾出”。在本书中,我们假设我们的数据被准确收集,是我们分析所需的正确数据,并且包含了代表性样本。我们一直在使用来自同行评审研究的知名数据集,所以这是一个安全的假设。
但通常您不能对数据如此确定;您可能需要负责收集和分析数据。因此,值得进一步学习关于研究设计和方法的内容。这个领域可以变得非常复杂和学术化,但在商业实验领域找到了实际应用。查阅斯蒂芬·H·汤姆克的《实验工作:商业实验的惊人力量》(哈佛商业评论出版社),了解如何以及为什么将良好的研究方法应用于业务。
进一步的统计方法
正如第四章提到的,我们仅仅触及了可用统计检验的表面,尽管其中许多都建立在假设检验的框架之上,该框架在第三章有所涵盖。
对于其他统计方法的概念性概述,请参阅萨拉·博斯劳的《Statistics in a Nutshell》(oreil.ly/gPll4),第二版(… Statistics for Data Scientists*》(oreil.ly/9LCBS),第二版(… R 和 Python 应用这些方法。正如其标题所示,后一本书跨越了统计学和数据科学之间的界限。
数据科学与机器学习
第五章审查了统计学、数据分析和数据科学之间的差异,并得出结论,尽管这些领域的方法有所不同,但更多的是它们的共同点而非分歧。
如果您对数据科学和机器学习兴趣浓厚,应集中学习 R 和 Python,还应具备一些 SQL 和数据库知识。要了解 R 在数据科学中的应用,请参阅 Hadley Wickham 和 Garrett Grolemund(O'Reilly)的《R for Data Science》,链接在这里。对于 Python,请参阅 Aurélien Géron(O'Reilly)的《Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow》(第二版),链接在这里。
版本控制
第五章 也提到了可重复性的重要性。让我们看看在这场战斗中的一个关键应用。您可能以前遇到过以下类似的一组文件:
-
proposal.txt
-
proposal-v2.txt
-
proposal-Feb23.txt
-
proposal-final.txt
-
proposal-FINAL-final.txt
或许一个用户创建了 proposal-v2.txt;另一个开始了 proposal-Feb23.txt。然后,还有 proposal-final.txt 和 proposal-FINAL-final.txt 之间的区别需要解决。很难弄清哪一个是“主要”副本,以及如何重建并迁移所有更改到该副本,同时记录谁贡献了什么。
版本控制系统 可以在这里提供帮助。这是一种跟踪项目的方法,例如不同用户进行的贡献和更改。版本控制对协作和跟踪修订具有革命性意义,但学习曲线相对较陡。
Git 是一种主流的版本控制系统,在数据科学家、软件工程师和其他技术专业人士中非常流行。特别是,他们经常使用基于云的托管服务 GitHub 来管理 Git 项目。有关 Git 和 GitHub 的概述,请参阅 Jon Loeliger 和 Matthew McCullough(O'Reilly)的《Version Control with Git》(第二版),链接在这里。如需了解如何将 Git 和 GitHub 与 R 和 RStudio 配对,请参阅 Jenny Bryan 等人的在线资源《Happy Git and GitHub for the useR》,链接在这里。目前在数据分析工作流中,Git 和其他版本控制系统相对不常见,但由于对可重复性的需求增加,它们正日渐流行起来。
伦理学
从记录和收集数据到分析和建模,数据被伦理问题所围绕。在第三章中,您了解到了统计偏差的问题:特别是在机器学习的背景下,模型可能会以不公正或非法的方式开始歧视某些群体。如果正在收集个人数据,则应考虑这些个人的隐私和同意问题。
在数据分析和数据科学中,道德并不总是优先考虑的问题。幸运的是,情况似乎在这里发生了变化,并且只会在持续的社区支持下继续下去。关于如何将伦理标准纳入数据处理工作的简要指南,请参阅 Mike Loukides 等人的《伦理与数据科学》(O’Reilly)。
出发吧,按照你自己的方式处理数据
经常有人问我,考虑到雇主需求和流行趋势,应该专注于这些工具中的哪一个。我的回答是:花些时间找出你喜欢的东西,让这些兴趣塑造你的学习路径,而不是试图迎合分析工具的“下一个大事”。这些技能都是非常有价值的。比任何一个分析工具更重要的是能够将这些工具放在背景中进行比较和配对,这需要接触广泛的应用。但你不可能成为所有事情的专家。最佳的学习策略将类似于“T”形:广泛接触各种数据工具,并在其中几个领域有相对深入的了解。
结语
请花一点时间回顾一下你通过这本书所取得的一切:你应该感到自豪。但不要停留:还有很多东西需要学习,在学习过程中不久你就会意识到这本书对你而言只是冰山一角。这是你的章节末和书末的练习:走出去,继续学习,并不断进步到分析领域。