美文网首页呆鸟的Python数据分析呆鸟译Py
不会爬,没数据?没关系!3分钟搞定1w+数据,超实用!​

不会爬,没数据?没关系!3分钟搞定1w+数据,超实用!​

作者: 呆鸟的简书 | 来源:发表于2020-01-16 17:58 被阅读0次

    Pandas 百问百答第 009 篇。

    呆鸟云:“以前常说,没有困难,创造困难也要上!现在我们说,没有数据,创造数据,也要学!

    老黄是个财务,但他不甘于只做财务,最近一直在积极学习 Python,从连 jupyter notebook 是啥都不知道,短短几个月,就已经 Pandas 上手各种玩了。

    用呆鸟的话说,“尊重是自己挣回来的,不是别人给的。” 老黄这种求知若渴、积极主动的精神赢得了呆鸟的尊重。但老黄也会遇到一些问题,且看下面的对话:

    老黄:“呆鸟哥,最近感觉遇到瓶颈了,毕竟不是干数据分析的,没数据啊!”

    呆鸟:“你可以用爬虫啊,想要啥数据就去爬。”

    老黄:“爬虫还没学呢,再说了,毕竟不是科班儿出身,Pandas 还没学好呢,再去学爬虫,又是一大厚本书,一时半会儿也学不会啊。我还是想先把 Pandas 学扎实了。”

    呆鸟:“呃……,说的也有道理,爬虫我也学得一知半解,而且爬虫有风险,用起来要谨慎。这样吧,说说你想用啥数据,看看能不能做些模拟数据。”

    老黄的需求

    1. 模拟一个超市连锁公司的销售订单表
    2. 在不同城市里有不同门店,门店里有不同销售人员
    3. 超市销售不同产品,每个产品对应不同的单价
    4. 生成不同订单,对应不同客人、售货员、分公司、产品、单价、数量、金额等
    5. 一年内每天都有不同的订单

    呆鸟的思路

    1. 写个字典,列出不同分公司与销售员
    2. 写个字典,列出不同产品与单价

    当然,写个 df 也可以,为了直观,这里用的字典;

    1. 写个随机生成日期的函数
    2. 先生成一个空 df,再用循环生成交易日期、客户ID、售货员、分公司、产品、单价、数量、订单金额。
    3. 用 DataFrame 的 append() 把每条数据加进去

    这样一来,模拟数据就成型了。用这种方式可以生成各种关系的模拟数据,还可以用 SQLAlchemy,把多个表放到模拟数据库里。呆鸟就曾弄过,还可以添加外键,可惜后来文件被误删除了,有兴趣的朋友,自己尝试下。

    说清楚了需求,下面,我们来一步步实现:

    一. 导入支持库

    import pandas as pd
    import numpy as np
    from datetime import datetime
    

    二. 编写分公司与销售员的字典

    sales_people = {"陈天浩": "上海",
                    "孙健": "上海",
                    "王梓戎": "广东",
                    "刘丹": "上海",
                    "刘颖": "上海",
                    "刘雪": "天津",
                    "章洋": "上海",
                    "殷琳": "广东",
                    "李辉": "北京",
                    "王玉": "吉林",
                    "侯宁": "上海",
                    "吴中岳": "广东",
                    "张林": "广东",
                    "庄雷": "上海",
                    "王宇": "吉林",
                    "利坤": "上海",
                    "董丹丹": "广东",
                    "蔡建平": "山东",
                    "陈杨": "吉林",
                    "蔡勇": "广东",
                    "李琳": "上海",
                    "魏苍生": "天津",
                    "刘帆": "天津",
                    "戴雪": "上海",
                    "许亮": "吉林",
                    "李智童": "山东",
                    "钱国": "山东",
                    "郭华锋": "吉林",
                    "阎云": "山东",
                    "江敏": "上海"}
    

    三. 编写产品与单价对应关系的字典

    products = {"苹果": 10,
              "梨": 8,
              "桃": 6.5,
              "葡萄": 15,
              "椰子": 20,
              "西瓜": 30,
              "百香果": 12,
              "榴莲": 50,
              "桔子": 6,
              "香蕉": 7.5}
    

    四. 编写随机日期生成器

    def random_dater(start_date, end_date):
        p_start_date = datetime.strptime(start_date, '%Y-%m-%d')
        p_end_date = datetime.strptime(end_date, '%Y-%m-%d')
        
        days_delta = p_end_date - p_start_date
        days_to_add = np.arange(0, days_delta.days)
        
        random_date = np.datetime64(
            start_date) + np.random.choice(days_to_add)  # numpy 也可以转换日期
        
        return random_date
    

    知识点:

    1. 这个函数的目的是,输入起止日期,就可以返回一个在起止日期范围内的随机日期
    2. 计算两个日期之间的天数,days_delta = p_end_date - p_start_date
    3. 用 np.arange() 生成一个从 0 天到间隔天数之间的数组,days_to_add = np.arange(0, days_delta.days)
    4. 随机选择一个数字,与开始日期相加,从而生成一个随机日期,random_date = np.datetime64(start_date) + np.random.choice(days_to_add),注意这里的 np.random.choice() 函数,就是用来随机选择数字的。

    五. 创建带列名的空 DataFrame

    如果你还不会创建空 DataFrame,关注一下这个知识点:

    sales0 = pd.DataFrame(
        columns=["交易日期", "客户ID", "售货员", "分公司", "产品", "单价", "数量", "订单金额"])
    

    六、写个循环插入数据

    for i in range(0, 10000):
        date = random_dater('2019-01-01', '2019-12-31')
        customer_id = "C" + str(np.random.randint(1, 1000)).zfill(4)
        sales_person = np.random.choice(list(sales_people))
        region = sales_people[sales_person]
        product = np.random.choice(list(products))
        price = products[product]
        quantity = np.random.randint(1, 10000)
        revenue = price * quantity
        sales0 = sales0.append(pd.Series([date, customer_id, sales_person,
                                 region, product, price, quantity, revenue], index=sales0.columns), ignore_index=True)
    

    知识点:

    1. 生成 C0001这样的数据,用 zfill() 函数,参数4,代表4位数字 ~ 0001
    2. 生成某个范围内的随机整数用 np.random.randint(),(1,1000) 代表生成的整数范围为 1 ~ 1000
    3. 从销售人员字典里随机选择一名销售员,np.random.choice(list(sales_people))
    4. sales_people[sales_person],按销售员姓名,提取分公司名称
    5. sales0.append() 函数负责按生成的数据按行添加到 DataFrame 里。要往 DataFrame 里添加行,就会用到这个函数。

    这段代码生成一万条模拟数据,在呆鸟 13 年出品的老电脑上,也只需要 1 分 18 秒。

    七、重新排序

    生成的随机数据是乱序的,要按交易日期、分公司、售货员排序。

    sales0.sort_values(['交易日期', '分公司', '售货员'], inplace=True)
    sales0.reset_index(drop=True,inplace=True)
    

    知识点:

    1. 按多列排序,直接写个列名的列表就可以了,如,['交易日期', '分公司', '售货员'];
    2. 要想排序直接生效,要用 inplace=True 参数
    3. 排序以后,索引是乱的,要重置索引,用 reset_index() 函数
    4. 抛弃之前的乱序索引,参数为 drop=True
    5. 要想重置索引直接生效,参数为 inplace=True
    6. 出一个小题目,自己思考下,如果想多列,按不同升降序排列,怎么处理?

    八、输出 Excel 文件

    sales0.to_excel('data/销售明细表0.xlsx', index=False)
    

    知识点:

    1. 输出时不含 DataFrame 的索引,用 index=False 参数
    2. 建议使用相对路径('data/销售明细表0.xlsx'),不要使用绝对路径('d:\\python\\data\\销售明细表0.xlsx'),相对路径的好处是文件移动到别的目录里或分享给别人的时候,不用手动修改目录,这就叫与人方便,与己方便!
    3. 要把数据文件与程序文件分开保存,这里,呆鸟把 Excel 文件保存在 data 子目录里,注意这里的写法:'data/销售明细表0.xlsx'

    至此,模拟的一万条数据就生成了,整个代码运行不超过 3 分钟。

    呆鸟兴冲冲地找老黄报喜:“老黄,你要的模拟数据搞定啦,以后这段程序,你改改就能生成各种各样的数据表了!”

    老黄:“感谢,感谢,以后再也不愁没数据用了!”

    未完待续

    一个小时后。。。。

    老黄郁闷地找到呆鸟:“呆鸟哥,我想用你的代码多生成点数据,结果一直运行不出来啊!”

    呆鸟:“你想要多少数据?”

    老黄:“100 万条。。。”

    呆鸟:“呃(⊙o⊙)…,你真有勇气,这样吧,咱们再想想还有什么办法,能把速度加上来!”

    相信也会有读者大大想到一万条数据太少了,怎么对得起 Pandas 的数据处理能力?但用 append() 函数添加大量数据确实效率很低,这一点其实在 Pandas 官档里也提到了,那怎么才能提高效率呢?效率又能提高多少呢?

    咱们且听下回分解。对这个问题感兴趣的朋友,请点喜欢,也让呆鸟看下有多少人关心这个问题。

    相关文章

      网友评论

        本文标题:不会爬,没数据?没关系!3分钟搞定1w+数据,超实用!​

        本文链接:https://www.haomeiwen.com/subject/xqfqzctx.html