寫在前面:說來真的很巧,先是有個人在一個qq比賽群裡扔了這個問題,我覺得很有意思,然後自己嘗試了下,就将自己寫的一段代碼發給了他。事後,在一個微信公衆号的推文裡,看到這篇文章資料城堡參賽代碼實戰篇(三)—我們來探究一個深奧的問題!裡面給了一些大神對同樣問題的解法,瞬間覺得自己很菜雞,把大神的和自己做個對比,提醒自己對于pandas的使用不能僅僅停留于表面,還有更多優化簡潔的處理方式需要學習!
OUTLINE:
- 問題描述
- 自己的解決方案
- 大神的更優化的解法
- 總結
問題描述
"""
id value
1 A
1 B
1 C
2 D
2 E
2 F
變為:
id value
1 [A,B,C]
2 [D,E,F]
pandas怎麼把上面的結構變為下面的形式?
"""
自己的解決方案
import pandas as pd
import numpy as np
data = pd.DataFrame({'id':[,,,,,],'value':['A','B','C','D','E','F']})
data1 = np.array(data.groupby(['id']))#按照id進行分類
# 轉變成array對象之後,可以根據data1[0][1]檢視其結構
id_kinds = #id的種類,此例比如1、2共兩種
all_value = []
for j in range():
value = []
for i in data1[j][]['value']:
value.append(i)
all_value.append(value)
print(all_value)
#再建立新的dataframe
new_data = pd.DataFrame({'id':[,],'value':all_value})
print(new_data)
輸出結果為:
id value
[A, B, C]
[D, E, F]
大神的更優化的解法
解法一:可以用sum方法,将字元串進行連接配接
import pandas as pd
import numpy as np
data = pd.DataFrame({'id':[1,1,1,2,2,2],'value':['A','B','C','D','E','F']})
data1 = data.groupby(by='id')['value'].sum()
此時的輸出結果為:
id
ABC
DEF
Name: value, dtype: object
但是還不是我們想要的,因為我們還需要在中間加入逗号分隔
① 我們可以先将原始資料的value都變成“,A”
data = pd.DataFrame({'id':[1,1,1,2,2,2],'value':['A','B','C','D','E','F']})
data['value'] = data['value'].apply(lambda x:','+ x)
② 然後,對其使用sum方法進行字元串相加
此時的輸出結果為,value值之前多了“,”
id value
,A,B,C
,D,E,F
③ 最後,對該列使用apply函數,去除‘,’
data1['value'] = data1['value'].apply(lambda x :[x[:]])
就得到了最終的結果:
id value
[A,B,C]
[D,E,F]
解法二:對分組之後的結果,直接使用apply函數
一行代碼就搞定!
那為什麼可以這麼做呢?
首先需要剖析的是,groupby之後的資料結構是什麼樣的,它是由元組構成的(分組名,資料塊),資料塊也就是dataframe結構。使用以下方式可以檢視groupby之後的對象:
for ID,group in group_df:
print(ID)
print(group)
apply函數中的x作用的即是資料塊(dataframe),通過資料塊取value那一行得到的是Series對象,于是可以使用join方法進行操作。
總結
- sum方法不僅可以用于數值計算,還可用于對于一個Series對象而言的字元串相加
a = ['a','b']
c = pd.Series(a).sum()
- apply函數非常靈活,不僅可以作用于一個Series對象,還可以作用于一個groupby之後的資料塊
data['value'].apply(lambda x :*****)
data.groupby(by='**').apply(lambda x :*****)
- lambda匿名函數可以極大優化精簡我們的代碼,是一個非常靈活好用的函數,記住它!