This commit is contained in:
louzefeng
2024-07-11 05:50:32 +00:00
parent bf99793fd0
commit d3828a7aee
6071 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
<audio id="audio" title="春节特别放送1实体水果店转线上销售的数据统计问题" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/05/7b/05d232f3c4af825c38a2e244bb252f7b.mp3"></audio>
你好,我是尹会生。今天是大年三十儿,先祝你春节快乐。同时我也要为假期还在坚持学习的你点赞。
春节期间我为你准备了一个项目作业帮助你检验第一模块的学习成果。这个作业由3个部分组成今天我会介绍项目背景给出你操作题目2月13号我会给出参考思路在2月16号我会公布答案。希望你跟着更新节奏完整地参与进来巩固你之前的学习成果。
接下来,我先介绍下项目情况。
这个题目来自我身边的一个真实案例。我先给你简单介绍下背景一家实体水果店上了多多买菜后店里的销售管理系统都没法直接使用实体店的那一套。而且像多多买菜、美团社群现在都只能下载Excel数据表。
题目是F水果店由于疫情原因2020年由实体店改为了线上销售。老板为了进行年终数据统计需要从在线管理软件下载Excel格式的销售数据并对销售数据进行处理分析各个种类的水果受欢迎的程度和库存量最后录入销售管理系统。不过老板在分析Excel的过程中遇到了这样一个问题。
将线上的数据转换为线下数据的时候由于数据不兼容必须进行统计和一定格式的调整。首先需要合并Excel统计全年水果销售量。在Excel中每个sheet记录了当日的销售数据每个Excel文件记录了当月的销售数据。图表如下
<img src="https://static001.geekbang.org/resource/image/7f/12/7fb84dcc1e0a4489ae0f9a8b9610a012.png" alt="">
我给你留两道题目:
1. 统计出全年每种水果的总销售额。
1. 统计出每月销售数量排名Top 3的水果。
欢迎你在留言区分享你对这道题的想法和思考我们一起交流、讨论。在2月13日也就是大年初二这一天我会把解题思路给你分享出来供你参考。

View File

@@ -0,0 +1,48 @@
<audio id="audio" title="春节特别放送2用自顶至底的思路解决数据统计问题" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/ec/a7/ecab6c669ee0e1a9426445f9a82bcaa7.mp3"></audio>
你好,我是尹会生。今天是大年初二,先祝你春节快乐。
上节课我策划了一个项目作业你完成得怎么样了呢如果你对第一模块的内容掌握了60%,其实这道题你就能完成得差不多了,或者说至少会有一个思路。那么今天这节课,我也来给你提供一些我的解题思路和解题方法。
我们再来回顾下两道题目:
1. 统计出全年每种水果的总销售额。
1. 统计出每月销售数量排名Top 3的水果。
因为这两道题目都是需要在统计数据的前提下进行的一个是统计之后进行求和一个是统计之后进行排序。所以我们优先要做的就是统计全部文件所有sheet里的单元格数据。
**以第一<strong><strong>题**</strong>为例,可以按照自顶至底的思路拆分问题。</strong>
什么是自顶至底呢?意思是分解问题的时候,先关注总体,再解决具体问题。我给你举个例子你会更容易理解。这是一个你熟悉的问题:怎样把大象装进冰箱?
你会马上想到,把大象装进冰箱分成三个步骤。你看,你不会关注冰箱是什么品牌,大象是什么品种,冰箱的容积如何,大象的体积有多大等等。这样思考的好处是你可以先对高层次的问题进行定义、设计、编码,再细节的问题,再其中的子任务或下一层次去解决。这样逐层去进行设计和编码能够让你的程序有更好的可读性。
那统计销售总数,我也可以把问题拆分成三个步骤。
- 第一步拆解Excel通过第二讲的循环功能取得每日销售数据。
- 第二步,读取每天里的每次销售金额数据。
- 第三步,将数据按照自己的算法(这里就是简单的累加)进行汇总。
接下来我带你具体看下每个步骤需要做什么。
首先,我们来取出每日销售数据。
你可以先从总销售额开始入手,思考如何拆解问题,。总销售额可以拆分成按月销售额的累加每月的销售数据可以存放到单独的文件中。月销售额可以拆分成日销售额的累加日销售额放在每个sheet中。
如果用python来实现总销售额的统计实现思路应该为通过pathlib库和for循环遍历文件读取每个Excel文件再通过xlrd库读取每个Excel里的每个sheet每个sheet里记录了每一天的销售数据,这样可以把每天的销售数据读取出来。
接着,我们来读取每一次销售数据。
由于Excel中除了销售金额还有日期等其他噪声数据我们只需要读取“水果名称”“销售金额”这两列必须数据就能实现统计销售总额的功能了。因此通过这两个数据所在的列取出“水果名称”“销售金额”这两列。
用python实现的话,就是使用for循环遍历每一行的水果再采用“字典”数据类型临时存放到Python的一种数据结构中。为什么要使用“字典”呢在第三讲我给你讲解过,“字典”适合记录有映射关系的一对或多对数据。
最后,将数据汇总在一起。
根据需求,销售的金额只需要记录汇总的金额就可以实现最终要求,也就是统计全年销售额的任务了。所以这一步具体做法就是:把字典中可以对每种水果的每次销售金额累加存放,就可以得到当日每种水果销售总金额了。
第二道题那如何来实现Top3功能呢?
这两道问题的处理思路非常相似都是需要处理每个月的销售额但是第一个问题统计全年销售额需要将12个月的销售数据进行累加。第二个问题需要对每个月的销售数据进行从大到小的排序前三位的就是“水果销售Top3”了。
你的思路和想法是什么呢可以在留言区分享一下我们一起交流、讨论。在2月16日也就是大年初五这一天我会把完整答案给你分享出来供你参考。

View File

@@ -0,0 +1,168 @@
<audio id="audio" title="春节特别放送3揭晓项目作业的答案" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/77/c8/771e1060c93ef2f0d2176d4bef361bc8.mp3"></audio>
前两节课,我给你策划了一个项目作业,也给你提供了解题思路和方法,那么今天,就是揭晓答案的时候了。不管你有没有完成作业,或者完成了多少,我都建议你在学习今天这节课的时候,一边看我的讲解,一边把你的答案与我讲解的答案进行对照。
不过我也要提醒你,因为现在你才学到了第三节课,所以答案对你来说并不是最重要的。重要的是你对前三节课的内容掌握了多少,以及这个项目作业的解题思路和方法。
话不多说,我们现在就开始吧。
## 第一题
我们先看第一道题中关于订单统计的处理思路。
**首先我们要明确要解决的问题。**
我们希望对多个Excel进行统计并取得每个Excel文件里的sheet。然后再从每一个sheet当中取出水果的名称和它的每一次销售金额最终要将多个Excel里的所有的数据进行合并。而合并之后就是我们想要的全年水果销售金额统计结果。
所以解决这个问题的关键点有两个。
**第一个关键知识点是遍历。**这个知识点在我们的第1讲、第2讲中都有提到。通过遍历的方式我们能依次取到每一个文件里的每一个sheet甚至能从每个sheet取出每一行的内容。
**第二个关键的知识点就是**<strong>多个元素的累加操作**</strong>。**主要就是把相同名称的水果销售金额进行计算。不过这里涉及到的计算很简单,就是累加操作,通过循环就可以实现多个元素的依次累加了。由于累加是针对每一行数据的,所以我们要把累加操作写在遍历每一行的循环当中。
在搞清楚了两个关键知识点之后,**接下来我来带你去分析一下<strong><strong>我实现全年销售统计的**</strong>代码。</strong>
```
import xlrd
from pathlib import Path, PurePath
from collections import defaultdict
# 订单路径
download_path = '/Users/edz/Desktop/效率专栏/新年特辑/订单'
# 取得该目录下所有的xlsx格式文件
p = Path(download_path)
files = [x for x in p.iterdir() if PurePath(x).match('*.xlsx')]
# 定义字典用于结果统计
total = defaultdict(int)
# 中文做字典的key会有问题,做两个简单的翻译函数
tran_dict = {
&quot;dragon_fruit&quot;:&quot;火龙果&quot;,
&quot;coconut&quot;:&quot;椰子&quot;,
&quot;watermelon&quot;:&quot;西瓜&quot;
}
# 中文翻译成英文
def dict_trans_chi2eng(value):
return [k for k,v in tran_dict.items() if v == value]
# 英文翻译成中文
def dict_name_eng2chi(key):
return tran_dict[key]
# 遍历文件
for file in files:
sheet = xlrd.open_workbook(file)
# 遍历表格
for table in sheet.sheets():
# 从第二行遍历内容
for line in range(1,table.nrows):
fruit = table.row_values(rowx=line, start_colx=0, end_colx=None)
# 第一列水果名称, 倒数第二列销售金额
# print(f'{fruit[0]},{fruit[-2]}')
# 火龙果,15.0
# 椰子,16.0
# 西瓜,10.5
# 统计每种水果的销售额
fruit_name = dict_trans_chi2eng(fruit[0])[0]
total[fruit_name] = total[fruit_name] + fruit[-2]
for fruit_name in total:
print(f'水果: {dict_name_eng2chi(fruit_name)} , 总金额: {total[fruit_name]}')
# 水果: 火龙果 , 总金额: 135.0
# 水果: 椰子 , 总金额: 144.0
# 水果: 西瓜 , 总金额: 94.5
```
我们来看代码的前3行。第1行是读取Excel文件的库第2行是用来去处理路径的库这两个库在我们课程的第一讲都已经为你重点讲解过。**读取<strong><strong>E**</strong>xcel使用的是xlrd库, 处理路径需要使用pathlib</strong>。之后的课程你也会多次看到它们,所以没有记住的话一定要再去复习。
我重点讲解一下第3行出现的库。第3行的库是一个叫做defaultdict的特殊字典。它特殊在哪里呢**和字典相比****defaultdict可以在**<strong>字典**</strong>初始化的时候**<strong>得到一个默认的**</strong>值。在我的代码中就使用defaultdict记录了水果数量默认把水果数量设置为0那就不用像默认字典一样设置了字典之后还要手动把字典的值赋值为0。
这三行都是程序引入的库,**接下来我们来看具体的代码逻辑**。
首先我们需要**获得Excel文件所在的路径**。第9、10行代码是用来读取目录下所有的Excel文件的获取路径使用的是第2讲的pathlib库我在第2讲也为你详细剖析过它的逻辑这里就不再赘述了。
获得路径之后,接着就要去**处理每一个文件**了。从**第30行**开始就是我们**程序的核心逻辑**像咱们的第二讲一样我在这里使用了三个for循环。
- 第1个循环用来遍历所有的Excel文件。
- 第2个循环用来遍历所有的sheet。
- 第3个循环用来读取文件当中的第2行到最后一行。
通过这些循环我就可以按行进行处理。那再接着需要处理的就是**如何进行水果销售金额的累加。**
如果你仔细观察代码就会发现,我并没有马上去进行累加,而是在这里做了一个**把中文转换成英文的额外处理**,这个额外的处理使用了第三讲学过的**自定义函数功能**。
你可能会问为什么要进行中文转换英文呢因为在Python程序当中字典这个数据类型对中文支持并不友好使用中文作为字典的key进行操作时会报错。
所以为了避免字典在处理中文的时候出现报错,我在这里做了一个**中文英文映射和转换**的一个小功能。这个功能被我写在文件当中的第15到第27行你会看到这里有一个**被定义为translate_dict的一个映射关系的字典**。
在这个字典当中Key就是英文单词value就是中文汉字。如果在你编写的程序当中需要支持更多的水果种类那你就可以按照我的格式在这个字典中继续去扩展中英文的映射关系。
那中英文转换又是怎么实现的呢我在字典之后又自定义了两个函数分别被我命名为Chinese to English和English to Chinese。
在有了中英文转换功能那我在进行水果的累加之前“Chinese to English”函数就可以把字典的“key”从中文的水果名称转换成英文。转换成英文就意味着英文的水果名称可以作为统计总金额的字典total的key。那么
- 使用total[fruit_name]方法就可以取得已经统计的水果金额。
- 使用fruit[-2]取得通过当前得到的水果金额。
- 使用total[fruit_name] = total[fruit_name] + fruit[-2] 方式,就可以实现全年的水果销售总金额统计功能。
最后在第49行**把<strong><strong>销售金额统计**</strong>结果进行输出</strong>。由于水果名称在处理过程被处理成英文,为了让你查看的结果更加友好,我还需要再做两件事情。
1. 第一个是我在输出前把英文的水果名称使用“English to Chinese”函数转换成了中文。
1. 第二个是使用了字符串连接功能,将输出的内容进行对齐并增加必要的提示信息,这样你就可以看到每种水果今年的销售总额了。
以上就是我在实现全年水果销售统计的问题上,是如何编码来实现的。
## 第二题
接下来我们再看第二个问题。第二个问题要求你按月进行水果销售额Top3的统计信息并且取出当月销售数量前三名的水果名称。
针对这道题,在进行编码之前我们要思考一下,按月统计数据和全年统计数据有什么区别?怎么才能取出销售数量的前三名呢?
咱们首先来解决按月统计数据和全年统计数据有什么区别这个问题。
回顾一下我们在解决全年统计问题的过程。我们先取得了每次销售数据。之后又使用了total字典类型统计了所有行的结果通过循环,将所有行的结果汇总成日数据和月数据,又继续通过循环将月数据统计为全年销售总额。
如果需要统计水果销售额Top3,我们也需要先将数据统计为月销售数据,之后不能将月数据合并到一起,而是需要对每个月的数据进行排序,取出销售最多的前三个水果销售额,所以统计月销售数据以前的程序逻辑是相同的,区别是统计月销售数据以后,一个是进行合并一个是进行排序操作。
那第二个问题怎样去取前三名呢我们要想取出前几名前提是要先进行数据的排序工作。因为排序之后才能从大到小取出销售量最高的前三名。为了实现排序这一功能我们必须要掌握Python的**排序和截取前三个元素的程序编写方法**。
所以接下来我们要学习的就是具体编码。由于和统计总金额的代码功能非常相似我们就直接复用统计总金额的获取文件路径统计月销售额的代码。由于每一个文件代表一个月份的销售数据所以我在第48行用输出文件名的方式告诉你当前在统计的文件是哪一个月份的。
通过上面的逻辑方法我们实现了按月统计销售额和输出当前月份的功能。接下来就可以进行后续的排序并且取出字典的value排前3的数据了。你可以通过比较传统的sort函数进行排序并采用复循环三次取出前3水果名称和销售数量。
不过我觉得采用这样的方式,代码其实不够简洁。所以我们还有另外一种简洁的方法。
在程序中我为了避免自己需要编程实现代码逻辑就直接引入了collections标准库的Counter包实现排序并提取前n个数的功能。Counter包支持对列表和字典进行排序、数量统计、取前n个数的功能非常强大。
那这里就用它来实现基于字典的value从大到小进行排序排序之后取前三个元素的功能来实现从而取得水果销售额Top3。
在代码的第53行就是我使用了Counter包实现对total变量进行排序的具体实现代码。
在排序之后接下来的问题就是如何取出前三个元素了。由于提取前N个元素的问题Counter包已经内置了该功能所以在第58行我可以再通过most_common()函数为函数增加数字“3”作为参数从而实现提取销量Top3的功能。
```
# 使用Counter函数排序和统计数量
sorted_total = Counter(total)
# 清空本月统计数据
total = defaultdict(int)
# 通过most_commnon函数排序取出Top3
print(sorted_total.most_common(3))
```
在这个程序当中我们也有一个要注意的事项。因为每个月份统计好的数据都会放到total变量当中因此在进行下一个月统计的时候total变量会把本月统计结果累加上去这样就会导致下一个月统计的数量不准确。
所以我们在统计完每一个月的统计数据之后需要把total变量重新初始化。为了能够让你注意这件事情我特意把它写在了第56行并详细进行了标注。这也是在进行数据统计时极容易犯错误的地方希望你能注意它的用法。
以上就是我实现所有水果的金额统计和按月统计的实现方法希望你能通过这两个代码理解如何去处理大批量重复的Excel工作。
好了,我们的春节策划到这节课就结束了,你的答案和我的一样吗?希望你能借助这个项目,查漏补缺,多多巩固前面的内容。下节课,我们继续来自动化办公的方法,我们下次见。