利用 Pandas 將資料集中的某列文字拆分為多行

飛天麵條發表於2019-02-12

背景

手頭的專案要求用 Tableau 建立一個 story,資料集是摩拜上海城區使用者使用資料。其中有一個維度的資料處理起來有點棘手。

資料格式

利用 Pandas 將資料集中的某列文字拆分為多行

注意 track 這個維度的資料,它表示的是在訂單時間內的行車軌跡,裡面包含了大量座標點。

按照 tidydata 的要求:

  • Each variable forms a column.
  • Each observation forms a row.
  • Each type of observational unit forms a table.

我需要將 track 的座標拆分為多行。

利用 Pandas 將資料集中的某列文字拆分為多行

神來之筆

Google 了問題的解決方式,程式碼是

mobike.drop("track",axis = 1).join(mobike["track"].str.split("#",expand = True).stack().reset_index(level = 1,drop = True).rename("track"))
複製程式碼

工作原理

解決問題不能光知其然,不知其所以然。所以我將這行程式碼逐語句進行了拆分,一探程式碼內部的工作原理。

最外層程式碼是:

mobike.join({dataset})
複製程式碼

這裡呼叫了 dataframe 的 join 方法,很基礎。

{dataset} 這部分做的工作比較多,首先是 split 方法。Python 的 split 方法可以將字串按照指定的字元進行分割,這個例子中指定的字元是「#」。如果不加引數 expand = Truesplit()會返回拆分後的字串陣列。

mobike["track"].str.split("#")
# ["121.372,31.118","121.372,31.119","121.373,31.117","1...]
# ["121.419,31.200","121.419,31.201","121.420,31.199","1...]
# ...
複製程式碼

加了 expand = True 會將陣列拆開,陣列中的每一個元素都會單獨儲存。

mobike["track"].str.split("#",expand = True)
# "121.372,31.118" "121.372,31.119" "121.373,31.117" "1... 
# "121.419,31.200" "121.419,31.201" "121.420,31.199" "1...
# ...
複製程式碼

到這裡相當於將列中所有文字拆成了一個巨大的表,表中每個單元格有一個值。有些行拆分後的元素比較少,沒有值可以填充的單元格補充 None

利用 Pandas 將資料集中的某列文字拆分為多行

stack() 會把整個表逐行堆疊成一列。

利用 Pandas 將資料集中的某列文字拆分為多行

這樣就成功的將一列中的所有文字拆分成了多行,而且它是一個 dataframe 。不過到這裡還沒有結束,我們還需要將拆出來的這個 dataframe 與原資料集合並。

注意到拆分出來的 dataframe 是多重索引的,需要用 reset_index() 將多重索引重置掉。在 split() 的時候,我們引入了超級多的 None。這時候就可以通過 reset_index(..., drop =True)將值為 None 的行刪除。

與原資料集通過 join() 合併的時候,A.join(B),A、B兩個 DataFrame 都需要有名字,因此需要 rename("track")

至此,我們的任務算做完了。

彩蛋

我在列拆分為多行的基礎上,還將 track 拆分成了兩個變數——track_x,track_y。這裡用到了 pandas 的函式對映進行資料轉換。

mobike["track" = mobike["track"].split(",")
mobike["track_x"] = mobike["track"].map(lambda x:x[0])
mobike["track_y"] = mobike["track"].map(lambda x:x[1])
複製程式碼

通過 map 進行列的擴充套件速度非常非常快。

本文用到的摩拜資料及演示 notebook 均可在 DataWranglingMethod下載。

相關文章