天天看點

生死競速最後20分鐘拯救一道Pandas作業

👉作者首頁: 小小明-代碼實體

👉簡介:Python領域優質創作者🏆、資料處理專家✌

👉歡迎點贊 👍 收藏 ⭐留言 📝

生死競速最後20分鐘拯救一道Pandas作業

昨晚有位童鞋一道Pandas面試題完全沒有思路不會做,通過黃同學找到我時,這道題目離送出答案僅剩20分鐘,不過我最終還是在15分鐘之内解決了問題,這整個過程簡直是刺激~😱😱😱

生死競速最後20分鐘拯救一道Pandas作業

原題題目如下:

生死競速最後20分鐘拯救一道Pandas作業

最終要求輸出:

生死競速最後20分鐘拯救一道Pandas作業

要在20分鐘内解決這個問題,對于我來說最困難的第一步就是了解題意,作為一名英文渣渣,硬看這個還是了解的太慢。ε=ε=ε=(#>д<)ノ啊啊啊,簡直是生死競速啊,怎麼辦?

最終我使用了騰訊翻譯官進行輔助,翻譯結果如下:

生死競速最後20分鐘拯救一道Pandas作業

有了圖檔翻譯工具,這個題目總算了解了。

我總結一下四個規則要求:對于每一天的每一支股票,會有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           
生死競速最後20分鐘拯救一道Pandas作業

這四個規則,直接使用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           

結果:

生死競速最後20分鐘拯救一道Pandas作業

可以看到結果滿足題目的四點規則要求,曆時5分鐘編碼終于搞定了。😪長舒一口氣壓壓驚~

做完後我立馬将代碼和截圖發給了對方,對方也在送出答案後立馬回了我一個紅包。

但是表達看不懂,希望我寫篇文章:

生死競速最後20分鐘拯救一道Pandas作業

既然如此,那麼我就寫下這篇文章來詳解這其中的幾個小知識點。雖然其實這其中涉及的内容比我以前的老文章要簡單20倍以上,不太屑于寫,但黃同學都這樣邀請了,我就逼自己寫一把吧😂

首先呢,我們将整個datafream按照每天每支股票拆分成一個個的Datafream:

for (date, ticker), df_split in df.groupby(["date", "ticker"]):
    print(date, ticker)
    display(df_split)           

結果如下:

生死競速最後20分鐘拯救一道Pandas作業

可以看到這支股票的每一天的資料都被拆分了出來。

取最頻繁的價格,我們可以使用衆數:

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參數指定了列名。

額,感覺實在太過于基礎已經沒啥可寫的了,推薦幾篇老文章吧: