不會爬,沒數據?沒關係!3分鐘搞定1w+數據,超實用!
摘要:生成的隨機數據是亂序的,要按交易日期、分公司、售貨員排序。如果你還不會創建空 DataFrame,關注一下這個知識點:。
老黃是個財務,但他不甘於只做財務,最近一直在積極學習 Python,從連 jupyter notebook 是啥都不知道,短短几個月,就已經 Pandas 上手各種玩了。
用呆鳥的話說,“ 尊重是自己掙回來的,不是別人給的。 ” 老黃這種求知若渴、積極主動的精神贏得了呆鳥的尊重。 但老黃也會遇到一些問題,且看下面的對話:
老黃: “呆鳥哥,最近感覺遇到瓶頸了,畢竟不是幹數據分析的,沒數據啊! ”
呆鳥: “你可以用爬蟲啊,想要啥數據就去爬。 ”
老黃: “爬蟲還沒學呢,再說了,畢竟不是科班兒出身,Pandas 還沒學好呢,再去學爬蟲,又是一大厚本書,一時半會兒也學不會啊。 我還是想先把 Pandas 學紮實了。 ”
呆鳥: “呃……,說的也有道理,爬蟲我也學得一知半解,而且爬蟲有風險,用起來要謹慎。 這樣吧,說說你想用啥數據,看看能不能做些模擬數據。 ”
老黃的需求:
-
模擬一個超市連鎖公司的銷售訂單表
-
不同城市裏有不同門店,門店裏有不同銷售人員
-
超市銷售不同產品,每個產品對應不同的單價
-
生成不同訂單,對應不同客人、售貨員、分公司、產品、單價、數量、金額等
-
一年內每天都有不同的訂單
呆鳥的思路:
-
寫個字典,列出不同分公司與銷售員
-
寫個字典,列出不同產品與單價
當然,寫個 df 也可以,爲了直觀,這裏用的字典;
-
寫個隨機生成日期的函數
-
先生成一個空 df,再用循環生成交易日期、客戶ID、售貨員、分公司、產品、單價、數量、訂單金額。
-
用 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
知識點:
-
這個函數的目的是,輸入起止日期,就可以返回一個在起止日期範圍內的隨機日期
-
計算兩個日期之間的天數,
days_delta = p_end_date - p_start_date
-
用 np.arange() 生成一個從 0 天到間隔天數之間的數組,
days_to_add = np.arange(0, days_delta.days)
-
隨機選擇一個數字,與開始日期相加,從而生成一個隨機日期,
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)
知識點:
-
生成 C0001這樣的數據,用
zfill()
函數,參數4,代表4位數字 ~ 0001 -
生成某個範圍內的隨機整數用
np.random.randint()
,(1,1000) 代表生成的整數範圍爲 1 ~ 1000 -
從銷售人員字典裏隨機選擇一名銷售員,
np.random.choice(list(sales_people))
-
sales_people[sales_person]
,按銷售員姓名,提取分公司名稱 -
sales0.append()
函數負責按生成的數據 按行 添加到 DataFrame 裏。 要往 DataFrame 裏添加行,就會用到這個函數。
這段代碼生成一萬條模擬數據,在呆鳥 13 年出品 的老電腦上,也只需要 1 分 18 秒。
七、重新排序
生成的隨機數據是亂序的,要按交易日期、分公司、售貨員排序。
sales0.sort_values(['交易日期', '分公司', '售貨員'], inplace=True) sales0.reset_index(drop=True,inplace=True)
知識點:
-
按多列排序,直接寫個列名的列表就可以了,如,
['交易日期', '分公司', '售貨員']
; -
要想排序直接生效,要用
inplace=True
參數 -
排序以後,索引是亂的,要重置索引,用
reset_index()
函數 -
拋棄之前的亂序索引,參數爲
drop=True
-
要想重置索引直接生效,參數爲
inplace=True
-
出一個小題目,自己思考下,如果想多列,按不同升降序排列,怎麼處理?
八、輸出 Excel 文件
sales0.to_excel('data/銷售明細表0.xlsx', index=False)
知識點:
-
輸出時不含 DataFrame 的索引,用
index=False
參數 -
建議使用相對路徑(
'data/銷售明細表0.xlsx'
),不要使用絕對路徑('d:\python\data\銷售明細表0.xlsx'
),相對路徑的好處是文件移動到別的目錄裏或分享給別人的時候,不用手動修改目錄,這就叫與人方便,與己方便! -
要把數據文件與程序文件分開保存,這裏,呆鳥把 Excel 文件保存在 data 子目錄裏,注意這裏的寫法:
'data/銷售明細表0.xlsx'
。
至此,模擬的一萬條數據就生成了,整個代碼運行不超過 3 分鐘。
呆鳥興沖沖地找老黃報喜: “老黃,你要的模擬數據搞定啦,以後這段程序,你改改就能生成各種各樣的數據表了! ”
老黃: “感謝,感謝,以後再也不愁沒數據用了! ”
未完待續
一個小時後。 。。。
老黃鬱悶地找到呆鳥: “呆鳥哥,我想用你的代碼多生成點數據,結果一直運行不出來啊! ”
呆鳥: “你想要多少數據? ”
老黃: “100 萬條。 。 。 ”
呆鳥: “呃(⊙o⊙)…,你真有勇氣,這樣吧,咱們再想想還有什麼辦法,能把速度加上來! ”
相信也會有讀者大大想到一萬條數據太少了,怎麼對得起 Pandas 的數據處理能力? 但用 append() 函數添加大量數據確實效率很低,這一點其實在 Pandas 官檔裏也提到了, 那怎麼才能提高效率呢? 效率又能提高多少呢?