Browse Source

更新了数据分析部分的文档

jackfrued 4 years ago
parent
commit
08bc838dcd

File diff suppressed because it is too large
+ 423 - 350
Day36-40/36-38.关系型数据库MySQL.md


+ 484 - 0
Day66-80/73.Pandas的应用-4.md

@@ -0,0 +1,484 @@
+## Pandas的应用-4
+
+### DataFrame的应用
+
+#### 数据分析
+
+经过前面的学习,我们已经将数据准备就绪而且变成了我们想要的样子,接下来就是最为重要的数据分析阶段了。当我们拿到一大堆数据的时候,如何从数据中迅速的解读出有价值的信息,这就是数据分析要解决的问题。首先,我们可以获取数据的描述性统计信息,通过描述性统计信息,我们可以了解数据的集中趋势和离散趋势。
+
+例如,我们有如下所示的学生成绩表。
+
+```Python
+import numpy as np
+import pandas as pd
+
+scores = np.random.randint(50, 101, (5, 3))
+names = ('关羽', '张飞', '赵云', '马超', '黄忠')
+courses = ('语文', '数学', '英语')
+df = pd.DataFrame(data=scores, columns=courses, index=names)
+df
+```
+
+输出:
+
+```
+     语文   数学   英语
+关羽  96    72    73
+张飞  72    70	97
+赵云  74    51	79
+马超  100   54	54
+黄忠  89    100	88
+```
+
+我们可以通过`DataFrame`对象的方法`mean`、`max`、`min`、`std`、`var`等方法分别获取每个学生或每门课程的平均分、最高分、最低分、标准差、方差等信息,也可以直接通过`describe`方法直接获取描述性统计信息,代码如下所示。
+
+计算每门课程成绩的平均分。
+
+```Python
+df.mean()
+```
+
+输出:
+
+```
+语文    86.2
+数学    69.4
+英语    78.2
+dtype: float64
+```
+
+计算每个学生成绩的平均分。
+
+```Python
+df.mean(axis=1)
+```
+
+输出:
+
+```
+关羽    80.333333
+张飞    79.666667
+赵云    68.000000
+马超    69.333333
+黄忠    92.333333
+dtype: float64
+```
+
+计算每门课程成绩的方差。
+
+```Python
+df.var()
+```
+
+输出:
+
+```
+语文    161.2
+数学    379.8
+英语    265.7
+dtype: float64
+```
+
+> **说明**:通过方差可以看出,数学成绩波动最大,最不稳定。
+
+获取每门课程的描述性统计信息。
+
+```Python
+df.describe()
+```
+
+输出:
+
+```
+        语文        数学         英语
+count   5.000000	5.000000	5.000000
+mean    86.200000	69.400000	78.200000
+std     12.696456	19.488458	16.300307
+min     72.000000	51.000000	54.000000
+25%     74.000000	54.000000	73.000000
+50%     89.000000	70.000000	79.000000
+75%     96.000000	72.000000	88.000000
+max     100.000000	100.000000	97.000000
+```
+
+##### 排序和Top-N
+
+如果需要对数据进行排序,可以使用`DataFrame`对象的`sort_values`方法,该方法的`by`参数可以指定根据哪个列或哪些列进行排序,而`ascending`参数可以指定升序或是降序。例如,下面的代码展示了如何将学生表按语文成绩排降序。
+
+```Python
+df.sort_values(by='语文', ascending=False)
+```
+
+输出:
+
+```
+      语文   数学   英语
+马超	100    54	  54
+关羽	96     72     73
+黄忠	89     100    88
+赵云	74     51     79
+张飞	72     70     97
+```
+
+如果`DataFrame`数据量很大,排序将是一个非常耗费时间的操作。有的时候我们只需要获得排前N名或后N名的数据,这个时候其实没有必要对整个数据进行排序,而是直接利用堆结构找出Top-N的数据。`DataFrame`的`nlargest`和`nsmallest`方法就提供对Top-N操作的支持,代码如下所示。
+
+找出语文成绩前3名的学生信息。
+
+```Python
+df.nlargest(3, '语文')
+```
+
+输出:
+
+```
+      语文   数学   英语
+马超	100    54	  54
+关羽	96     72     73
+黄忠	89     100    88
+```
+
+找出数学成绩最低的3名学生的信息。
+
+```Python
+df.nsmallest(3, '数学')
+```
+
+输出:
+
+```
+      语文  数学  英语
+赵云  74    51	79
+马超  100   54	54
+张飞  72    70	97
+```
+
+##### 分组聚合操作
+
+我们先从 Excel 文件中读取一组销售数据,然后再为大家演示如何进行分组聚合操作。
+
+```Python
+df = pd.read_excel('2020年销售数据.xlsx')
+df.head()
+```
+
+> **说明**:如果需要上面例子中的 Excel 文件,可以通过下面的阿里云盘地址进行获取,该文件在“我的分享”下面的“数据集”目录中。地址:https://www.aliyundrive.com/s/oPi7DRAVKRm。
+
+输出:
+
+```
+    销售日期	 销售区域   销售渠道  销售订单     品牌    售价  销售数量
+0   2020-01-01  上海       拼多多    182894-455  八匹马  99    83
+1   2020-01-01  上海       抖音      205635-402  八匹马  219   29
+2   2020-01-01  上海       天猫      205654-021  八匹马  169   85
+3   2020-01-01  上海       天猫      205654-519  八匹马  169   14
+4   2020-01-01  上海       天猫      377781-010  皮皮虾  249   61
+```
+
+如果我们要统计每个销售区域的销售总额,可以先通过“售价”和“销售数量”计算出销售额,为`DataFrame`添加一个列,代码如下所示。
+
+```Python
+df['销售额'] = df['售价'] * df['销售数量']
+df.head()
+```
+
+输出:
+
+```
+    销售日期	 销售区域   销售渠道  销售订单     品牌    售价  销售数量  销售额
+0   2020-01-01  上海       拼多多    182894-455  八匹马  99    83        8217
+1   2020-01-01  上海       抖音      205635-402  八匹马  219   29        6351
+2   2020-01-01  上海       天猫      205654-021  八匹马  169   85        14365
+3   2020-01-01  上海       天猫      205654-519  八匹马  169   14        2366
+4   2020-01-01  上海       天猫      377781-010  皮皮虾  249   61        15189
+```
+
+然后再根据“销售区域”列对数据进行分组,这里我们使用的是`DataFrame`对象的`groupby`方法。分组之后,我们取“销售额”这个列在分组内进行求和处理,代码和结果如下所示。
+
+```Python
+df.groupby('销售区域').销售额.sum()
+```
+
+输出:
+
+```
+销售区域
+上海    11610489
+北京    12477717
+南京     1767301
+安徽      895463
+广东     1617949
+江苏      537079
+浙江      687862
+福建    10178227
+Name: 销售额, dtype: int64
+```
+
+如果我们要统计每个月的销售总额,我们可以将“销售日期”作为groupby`方法的参数,当然这里需要先将“销售日期”处理成月,代码和结果如下所示。
+
+```Python
+df.groupby(df['销售日期'].dt.month).销售额.sum()
+```
+
+输出:
+
+```
+销售日期
+1     5409855
+2     4608455
+3     4164972
+4     3996770
+5     3239005
+6     2817936
+7     3501304
+8     2948189
+9     2632960
+10    2375385
+11    2385283
+12    1691973
+Name: 销售额, dtype: int64
+```
+
+接下来我们将难度升级,统计每个销售区域每个月的销售总额,这又该如何处理呢?事实上,`groupby`方法的第一个参数可以是一个列表,列表中可以指定多个分组的依据,大家看看下面的代码和输出结果就明白了。
+
+```Python
+df.groupby(['销售区域', df['销售日期'].dt.month]).销售额.sum()
+```
+
+输出:
+
+```
+销售区域  销售日期
+上海      1       1679125
+          2       1689527
+          3       1061193
+          4       1082187
+          5        841199
+          6        785404
+          7        863906
+          8        734937
+          9       1107693
+         10       412108
+         11       825169
+         12       528041
+北京     1       1878234
+         2       1807787
+         3       1360666
+         4       1205989
+         5        807300
+         6       1216432
+         7       1219083
+         8        645727
+         9        390077
+        10       671608
+        11       678668
+        12       596146
+南京     7        841032
+        10       710962
+        12       215307
+安徽     4        341308
+         5        554155
+广东     3        388180
+         8        469390
+         9        365191
+        11       395188
+江苏     4        537079
+浙江     3        248354
+         8        439508
+福建     1       1852496
+         2       1111141
+         3       1106579
+         4        830207
+         5       1036351
+         6        816100
+         7        577283
+         8        658627
+         9        769999
+        10       580707
+        11       486258
+        12       352479
+Name: 销售额, dtype: int64
+```
+
+如果希望统计出每个区域的销售总额以及每个区域单笔金额的最高和最低,我们可以在`DataFrame`或`Series`对象上使用`agg`方法并指定多个聚合函数,代码和结果如下所示。
+
+```Python
+df.groupby('销售区域').销售额.agg(['sum', 'max', 'min'])
+```
+
+输出:
+
+```
+          sum        max        min
+销售区域			
+上海      11610489   116303     948
+北京      12477717   133411     690
+南京      1767301    87527      1089
+安徽      895463     68502      1683
+广东      1617949    120807     990
+江苏      537079     114312     3383
+浙江      687862     90909      3927
+福建      10178227   87527      897
+```
+
+如果希望自定义聚合后的列的名字,可以使用如下所示的方法。
+
+```Python
+df.groupby('销售区域').销售额.agg(销售总额='sum', 单笔最高='max', 单笔最低='min')
+```
+
+输出:
+
+```
+          销售总额   单笔最高    单笔最低
+销售区域			
+上海      11610489   116303     948
+北京      12477717   133411     690
+南京      1767301    87527      1089
+安徽      895463     68502      1683
+广东      1617949    120807     990
+江苏      537079     114312     3383
+浙江      687862     90909      3927
+福建      10178227   87527      897
+```
+
+如果需要对多个列使用不同的聚合函数,例如“统计每个销售区域销售额的平均值以及销售数量的最低值和最高值”,我们可以按照下面的方式来操作。
+
+```Python
+df.groupby('销售区域')[['销售额', '销售数量']].agg({
+    '销售额': 'mean', '销售数量': ['max', 'min']
+})
+```
+
+输出:
+
+```
+         销售额        销售数量
+         mean          max    min
+销售区域			
+上海     20622.538188  100    10
+北京     20125.350000  100    10
+南京     22370.898734  100    11
+安徽     26337.147059  98     16
+广东     32358.980000  98     10
+江苏     29837.722222  98     15
+浙江     27514.480000  95     20
+福建     18306.163669  100    10
+```
+
+##### 透视表和交叉表
+
+上面的例子中,“统计每个销售区域每个月的销售总额”会产生一个看起来很长的结果,在实际工作中我们通常把那些行很多列很少的表成为“窄表”,如果我们不想得到这样的一个“窄表”,可以使用`DataFrame`的`pivot_table`方法或者是`pivot_table`函数来生成透视表。透视表的本质就是对数据进行分组聚合操作,**根据 A 列对 B 列进行统计**,如果大家有使用 Excel 的经验,相信对透视表这个概念一定不会陌生。例如,我们要“统计每个销售区域的销售总额”,那么“销售区域”就是我们的 A 列,而“销售额”就是我们的 B 列,在`pivot_table`函数中分别对应`index`和`values`参数,这两个参数都可以是单个列或者多个列。
+
+```Python
+pd.pivot_table(df, index='销售区域', values='销售额', aggfunc='sum')
+```
+
+输出:
+
+<img src="https://gitee.com/jackfrued/mypic/raw/master/20211106180912.png" style="zoom:50%">
+
+> **注意**:上面的结果操作跟之前用`groupby`的方式得到的结果有一些区别,`groupby`操作后,如果对单个列进行聚合,得到的结果是一个`Series`对象,而上面的结果是一个`DataFrame` 对象。
+
+如果要统计每个销售区域每个月的销售总额,也可以使用`pivot_table`函数,代码如下所示。
+
+```Python
+pd.pivot_table(df, index=['销售区域', df['销售日期'].dt.month], values='销售额', aggfunc='sum')
+```
+
+上面的操作结果是一个`DataFrame`,但也是一个长长的“窄表”,如果希望做成一个行比较少列比较多的“宽表”,可以将`index`参数中的列放到`columns`参数中,代码如下所示。
+
+```Python
+pd.pivot_table(
+    df, index='销售区域', columns=df['销售日期'].dt.month, 
+    values='销售额', aggfunc='sum', fill_value=0
+)
+```
+
+> **说明**:`pivot_table`函数的`fill_value=0`会将空值处理为`0`。
+
+输出:
+
+<img src="https://gitee.com/jackfrued/mypic/raw/master/20211106104551.png" style="zoom:50%">
+
+使用`pivot_table`函数时,还可以通过添加`margins`和`margins_name`参数对分组聚合的结果做一个汇总,具体的操作和效果如下所示。
+
+```Python
+df['月份'] = df['销售日期'].dt.month
+pd.pivot_table(
+    df, index='销售区域', columns='月份',
+    values='销售额', aggfunc='sum', fill_value=0, 
+    margins=True, margins_name='总计'
+)
+```
+
+输出:
+
+![image-20211106181707655](https://gitee.com/jackfrued/mypic/raw/master/20211106181707.png)
+
+交叉表就是一种特殊的透视表,它不需要先构造一个`DataFrame`对象,而是直接通过数组或`Series`对象指定两个或多个因素进行运算得到统计结果。例如,我们要统计每个销售区域的销售总额,也可以按照如下所示的方式来完成,我们先准备三组数据。
+
+```Python
+sales_area, sales_month, sales_amount = df['销售区域'], df['月份'], df['销售额']
+```
+
+使用`crosstab`函数生成交叉表。
+
+```Python
+pd.crosstab(
+    index=sales_area, columns=sales_month, values=sales_amount, aggfunc='sum'
+).fillna(0).applymap(int)
+```
+
+> **说明**:上面的代码使用了`DataFrame`对象的`fillna`方法将空值处理为0,再使用`applymap`方法将数据类型处理成整数。
+
+#### 数据可视化
+
+一图胜千言,我们对数据进行透视的结果,最终要通过图表的方式呈现出来,因为图表具有极强的表现力,能够让我们迅速的解读数据中隐藏的价值。和`Series`一样,`DataFrame`对象提供了`plot`方法来支持绘图,底层仍然是通过`matplotlib`库实现图表的渲染。关于`matplotlib`的内容,我们在下一个章节进行详细的探讨,这里我们只简单的讲解`plot`方法的用法。 
+
+例如,我们想通过一张柱状图来比较“每个销售区域的销售总额”,可以直接在透视表上使用`plot`方法生成柱状图。我们先导入`matplotlib.pyplot`模块,通过修改绘图的参数使其支持中文显示。
+
+```Python
+import matplotlib.pyplot as plt
+
+plt.rcParams['font.sans-serif'] = 'FZJKai-Z03S'
+```
+
+> **说明**:上面的`FZJKai-Z03S`是我电脑上已经安装的一种支持中文的字体的名称,字体的名称可以通过查看用户主目录下`.matplotlib`文件夹下名为`fontlist-v330.json`的文件来获得,而这个文件在执行上面的命令后就会生成。
+
+使用魔法指令配置生成矢量图。
+
+```Python
+%config InlineBackend.figure_format = 'svg'
+```
+
+绘制“每个销售区域销售总额”的柱状图。
+
+```Python
+temp = pd.pivot_table(df, index='销售区域', values='销售额', aggfunc='sum')
+temp.plot(figsize=(8, 4), kind='bar')
+plt.xticks(rotation=0)
+plt.show()
+```
+
+> **说明**:上面的第3行代码会将横轴刻度上的文字旋转到0度,第4行代码会显示图像。
+
+输出:
+
+<img src="https://gitee.com/jackfrued/mypic/raw/master/20211106195040.png" style="zoom:50%">
+
+如果要绘制饼图,可以修改`plot`方法的`kind`参数为`pie`,然后使用定制饼图的参数对图表加以定制,代码如下所示。
+
+```Python
+temp.sort_values(by='销售额', ascending=False).plot(
+    figsize=(6, 6), kind='pie', y='销售额', 
+    autopct='%.2f%%', pctdistance=0.8,
+    wedgeprops=dict(linewidth=1, width=0.35)
+)
+plt.legend(loc='center')
+plt.show()
+```
+
+输出:
+
+<img src="https://gitee.com/jackfrued/mypic/raw/master/20211106201550.png" style="zoom:50%">
+

+ 2 - 0
Day66-80/80.数据分析方法论.md

@@ -0,0 +1,2 @@
+## 数据分析方法论
+

+ 2 - 0
Day81-90/89.PyTorch概述.md

@@ -0,0 +1,2 @@
+## PyTorch入门
+

+ 0 - 2
Day81-90/89.Tensorflow概述.md

@@ -1,2 +0,0 @@
-## Tensorflow入门
-

+ 2 - 0
Day81-90/90.PyTorch实战.md

@@ -0,0 +1,2 @@
+## PyTorch实战
+

+ 0 - 2
Day81-90/90.Tensorflow实战.md

@@ -1,2 +0,0 @@
-## Tensorflow实战
-

+ 2 - 2
README.md

@@ -398,9 +398,9 @@ Python在以下领域都有用武之地。
 
 #### Day88 - [深度学习入门](./Day81-90/88.深度学习入门.md)
 
-#### Day89 - [Tensorflow概述](./Day81-90/89.Tensorflow概述.md)
+#### Day89 - [PyTorch概述](./Day81-90/89.PyTorch概述.md)
 
-#### Day90 - [Tensorflow实战](./Day81-90/90.Tensorflow实战.md)
+#### Day90 - [PyTorch实战](./Day81-90/90.PyTorch实战.md)
 
 ### Day91~100 - [团队项目开发](./Day91-100)
 

+ 19 - 19
番外篇/Python之禅的最佳翻译.md

@@ -1,24 +1,24 @@
 ## Zen of Python(Python之禅)
 
-1. Beautiful is better than ugly. (优美比丑陋好)
-2. Explicit is better than implicit.(清晰比晦涩好)
-3. Simple is better than complex.(简单比复杂好)
-4. Complex is better than complicated.(复杂比错综复杂好)
-5. Flat is better than nested.(扁平比嵌套好)
-6. Sparse is better than dense.(稀疏比密集好)
-7. Readability counts.(可读性很重要)
-8. Special cases aren't special enough to break the rules.(特殊情况也不应该违反这些规则)
-9. Although practicality beats purity.(但现实往往并不那么完美)
-10. Errors should never pass silently.(异常不应该被静默处理)
-11. Unless explicitly silenced.(除非你希望如此)
-12. In the face of ambiguity, refuse the temptation to guess.(遇到模棱两可的地方,不要胡乱猜测)
-13. There should be one-- and preferably only one --obvious way to do it.(肯定有一种通常也是唯一一种最佳的解决方案)
-14. Although that way may not be obvious at first unless you're Dutch.(虽然这种方案并不是显而易见的,因为你不是那个荷兰人[^1])
-15. Now is better than never.(现在开始做比不做好)
-16. Although never is often better than \*right\* now.(不做比盲目去做好[^2])
-17. If the implementation is hard to explain, it's a bad idea.(如果一个实现方案难于理解,它通常不是一个好的方案)
-18. If the implementation is easy to explain, it may be a good idea.(如果一个实现方案易于理解,它很有可能是一个好的方案)
-19. Namespaces are one honking great idea -- let's do more of those!(命名空间非常有用,我们应当多加利用)
+1. Beautiful is better than ugly. (优美比丑陋好)<br>
+2. Explicit is better than implicit.(清晰比晦涩好)<br>
+3. Simple is better than complex.(简单比复杂好)<br>
+4. Complex is better than complicated.(复杂比错综复杂好)<br>
+5. Flat is better than nested.(扁平比嵌套好)<br>
+6. Sparse is better than dense.(稀疏比密集好)<br>
+7. Readability counts.(可读性很重要)<br>
+8. Special cases aren't special enough to break the rules.(特殊情况也不应该违反这些规则)<br>
+9. Although practicality beats purity.(但现实往往并不那么完美)<br>
+10. Errors should never pass silently.(异常不应该被静默处理)<br>
+11. Unless explicitly silenced.(除非你希望如此)<br>
+12. In the face of ambiguity, refuse the temptation to guess.(遇到模棱两可的地方,不要胡乱猜测)<br>
+13. There should be one-- and preferably only one --obvious way to do it.(肯定有一种通常也是唯一一种最佳的解决方案)<br>
+14. Although that way may not be obvious at first unless you're Dutch.(虽然这种方案并不是显而易见的,因为你不是那个荷兰人[^1])<br>
+15. Now is better than never.(现在开始做比不做好)<br>
+16. Although never is often better than \*right\* now.(不做比盲目去做好[^2])<br>
+17. If the implementation is hard to explain, it's a bad idea.(如果一个实现方案难于理解,它通常不是一个好的方案)<br>
+18. If the implementation is easy to explain, it may be a good idea.(如果一个实现方案易于理解,它很有可能是一个好的方案)<br>
+19. Namespaces are one honking great idea -- let's do more of those!(命名空间非常有用,我们应当多加利用)<br>
 
 [^1]:这里指的是 Python 之父 Guido van Rossumm。
 [^2]:极限编程中的YAGNI原则

+ 2 - 2
番外篇/英语面试.md

@@ -26,9 +26,9 @@
 
 1. I: Can you tell me a little bit about yourself? (介绍下自己)
 
-   原则:不要谈私生活和奇怪的癖好(英雄联盟干到钻石),因为别人更想知道的是你的专业技能(qulifications)和工作经验(experience),所以重点在你之前的公司(company name)、职位(title)、时间(years)和主要职责(major responsibilities)
+   原则:不要谈私生活和奇怪的癖好(王者荣耀打到星耀并不值得在这里说),因为别人更想知道的是你的专业技能(qulifications)和工作经验(experience),所以重点在你之前的公司(company name)、职位(title)、时间(years)和主要职责(major responsibilities)
 
-   C: Thank you for having me. My name is Dachui WANG. I'm 25 years old, and I'm single. I have a Bachelor's Degree of Computer Science from Tsinghua University. I was a Junior Java Programmer for ABC Technologies during my college life. Then I become an intermediate Java engineer for XYZ Corporation in last two years. Programming is my everyday life and programming is where my passion is. I think I have a good knowledge of Java enterprise application developement using light-weight frameworks like Spring, Guice, Hibernate and other open source middle-ware like Dubbo, Mycat, rocketmq and so on and so forth. I love reading, travelling and playing basketball in my spare time. That's all! Thank you!
+   C: Thank you for having me. My name is Dachui WANG. I'm 22 years old, and I'm single. I have a Bachelor's Degree of Computer Science from Tsinghua University. I was a Junior Java Programmer for ABC Technologies during my college life. Then I become an intermediate Java engineer for XYZ Corporation in last two years. Programming is my everyday life and programming is where my passion is. I think I have a good knowledge of Java enterprise application developement using light-weight frameworks like Spring, Guice, Hibernate and other open source middle-ware like Dubbo, Mycat, rocketmq and so on and so forth. I love reading, travelling and playing basketball in my spare time. That's all! Thank you!
 
 2. I: How would you describe your personality? (你的性格)
 

Some files were not shown because too many files changed in this diff