👉作者首頁: 小小明-代碼實體👉簡介:Python領域優質創作者🏆、資料處理專家✌
👉歡迎點贊 👍 收藏 ⭐留言 📝
昨晚有位童鞋一道Pandas面試題完全沒有思路不會做,通過黃同學找到我時,這道題目離送出答案僅剩20分鐘,不過我最終還是在15分鐘之内解決了問題,這整個過程簡直是刺激~😱😱😱
原題題目如下:
最終要求輸出:
要在20分鐘内解決這個問題,對于我來說最困難的第一步就是了解題意,作為一名英文渣渣,硬看這個還是了解的太慢。ε=ε=ε=(#>д<)ノ啊啊啊,簡直是生死競速啊,怎麼辦?
最終我使用了騰訊翻譯官進行輔助,翻譯結果如下:
有了圖檔翻譯工具,這個題目總算了解了。
我總結一下四個規則要求:對于每一天的每一支股票,會有N個來源的價格,去掉空值後優先選擇最頻繁出現的價格,出現次數全部一樣時選擇來源id最小的價格,當天該股票全部都是空值時,選擇前一個交易日的價格。
搞清楚了規則就可以開始整理資料了,這裡我手敲編輯了資料為:
date | ticker | price | source_id |
---|---|---|---|
2013/1/2 | AAPL | 515.61 | |
515.62 | 1 | ||
2 | |||
2013/1/3 | 515.16 | ||
515.17 | |||
515.18 | |||
2013/1/4 | |||
515.45 | |||
515.47 | |||
2013/1/7 | |||
2013/1/8 | 527.28 | ||
528.29 |
儲存Excel檔案。
已經耗時10分鐘了😧怎麼辦?怎麼辦?😱
不過也已經到了我最擅長的編碼階段,開幹吧❗❗❗
首先使用pandas讀取資料:
import pandas as pd
df = pd.read_excel("股票資料.xlsx")
df
這四個規則,直接使用pandas本身的方法會導緻代碼較為臃腫。由于時間緊迫,這裡我直接使用萬能的循環來解決這個問題,最終完整代碼如下:
result = []
for (date, ticker), split in df.groupby(["date", "ticker"]):
prices = split.price.mode()
if prices.shape[0] > 0:
price = split.price.mode().iat[0]
else:
price = last
result.append((date, ticker, price))
last = price
result = pd.DataFrame(result, columns=["date", "ticker", "price"])
result
結果:
可以看到結果滿足題目的四點規則要求,曆時5分鐘編碼終于搞定了。😪長舒一口氣壓壓驚~
做完後我立馬将代碼和截圖發給了對方,對方也在送出答案後立馬回了我一個紅包。
但是表達看不懂,希望我寫篇文章:
既然如此,那麼我就寫下這篇文章來詳解這其中的幾個小知識點。雖然其實這其中涉及的内容比我以前的老文章要簡單20倍以上,不太屑于寫,但黃同學都這樣邀請了,我就逼自己寫一把吧😂
首先呢,我們将整個datafream按照每天每支股票拆分成一個個的Datafream:
for (date, ticker), df_split in df.groupby(["date", "ticker"]):
print(date, ticker)
display(df_split)
結果如下:
可以看到這支股票的每一天的資料都被拆分了出來。
取最頻繁的價格,我們可以使用衆數:
df_split.price.mode()
0 527.28
1 528.29
dtype: float64
這種形式表示衆數不止一個,表示出現次數一緻,此時規則2要求選擇來源id最小的價格,由于資料本身是按照來源id從小到大排序的,那麼我們直接取第一個衆數即可:
df_split.price.mode().iat[0]
527.28
但是問題是,某個分組可能出現價格全部為空值的情況,此時規則要求取前一個分組的價格,這也是我直接使用循環來解決這個問題的原因,因為可以通過一個變量記錄前一次周遊分組的結果。
當然為了避免資料源可能出現無序的情況的情況,我們需要事先對資料進行排序:
df.sort_values(["ticker", "date", "source_id"], inplace=True)
最後我将所有的結果資料都儲存到了一個清單中,通過DataFrame的構造函數則可以直接根據一個清單生成一個DataFrame,columns參數指定了列名。
額,感覺實在太過于基礎已經沒啥可寫的了,推薦幾篇老文章吧: