1. 程式人生 > >Pandas資料處理例項筆記(持續更新)

Pandas資料處理例項筆記(持續更新)

對單個xlsx檔案中全部工作簿進行合併

在一個xlsx檔案中存在多個worksheet,其中的資料格式一致,將所有worksheet進行拼接合並,並匯出csv

方法一:使用read_excel

import pandas as pd
df = pd.read_excel('xxx.xlsx', sheet_name=None, ignore_index=True)    #這裡注意要帶上後面的兩個引數,否則會只加載第一個工作簿的資料
cdf = pd.concat(df.values())
cdf.to_csv('new.csv')

方法二:使用ExcelFile.pares

import pandas as pd

file = pd.ExcelFile('0629.xls')
print(file.sheet_names)
df = []
for sheet in file.sheet_names:
    df.append(file.parse(sheet))

cdf = pd.concat(df)
cdf.to_csv('concat.csv')
print('Job Done')

將DataFrame匯出檔案

df.to_excel('aaa.xlsx')    # 需要xlwt包的支援,用之前pip install xlwt一下,匯出xlsx格式速度會比較慢,資料量大的時候不推薦
df.to_csv('bbb.csv', index=False, encoding='gb2312')    # index=False指定匯出的檔案中不帶資料行號列,encoding指定檔案編碼,win下面必須指定gb2312,否則excel開啟中文亂碼

對DataFrame中的資料進行分類,然後獲取每一分類的前n條

grouped = df.groupby(['class']).head(2)

使用列名對DataFrame進行資料選取

df[col]  #根據列名,並以Series的形式返回列
df[[col1, col2]]  #以DataFrame形式返回多列

使用iloc對DataFrame進行資料選取

# Single selections using iloc and DataFrame
# Rows:
data.iloc[0] # first row of data frame (Aleshia Tomkiewicz) - Note a Series data type output.
data.iloc[1] # second row of data frame (Evan Zigomalas)
data.iloc[-1] # last row of data frame (Mi Richan)
# Columns:
data.iloc[:,0] # first column of data frame (first_name)
data.iloc[:,1] # second column of data frame (last_name)
data.iloc[:,-1] # last column of data frame (id)

根據條件進行資料篩選

df[df[col] > 0.5]  # 選擇col列的值大於0.5的行
df[df.iloc[:,15]=='xxx']  # 選擇第15列(列標從0開始)等於xxx的行

檢視DataFrame物件資料總行數

len(df)

Series型別物件合併兩列資料

Series A和B進行合併計算

s1.combine_first(s2)

DataFrame相減處理(集合處理,不是資料減法計算)

How to remove a pandas dataframe from another dataframe, just like the set subtraction:

a=[1,2,3,4,5]
b=[1,5]
a-b=[2,3,4]

And now we have two pandas dataframe, how to remove df2 from df1:

In [5]: df1=pd.DataFrame([[1,2],[3,4],[5,6]],columns=['a','b'])
In [6]: df1
Out[6]:
   a  b
0  1  2
1  3  4
2  5  6


In [9]: df2=pd.DataFrame([[1,2],[5,6]],columns=['a','b'])
In [10]: df2
Out[10]:
   a  b
0  1  2
1  5  6

Then we expect df1-df2 result will be:

In [14]: df
Out[14]:
   a  b
0  3  4

Use pd.concat followed by drop_duplicates(keep=False)

pd.concat([df1, df2, df2]).drop_duplicates(keep=False)

It looks like

   a  b
1  3  4

續接兩個Series物件

s1 = pd.Series([1,2,3])
s2 = pd.Series([2,5,6,7,8])
s = s1.append(s2)
# s:[1,2,3,2,5,6,7,8]

統計檢視DataFrame/Series重複資料

例如上面的拼接後的s物件,其中的數值2是存在重複的,那麼要檢視的話這樣操作:

>>> s
0    1
1    2
2    3
0    2
1    5
2    6
3    7
4    8
dtype: int64
>>> s.duplicated()    # 檢視重複情況,不過這個結果看起來很不友好的,主要是用於獲得重複資料的bool結果
0    False
1    False
2    False
0     True
1    False
2    False
3    False
4    False
dtype: bool
>>> s[s.duplicated()]    # 檢視重複的具體資料
0    2
dtype: int64
>>> s[s.duplicated()].count()    # 統計重複資料數量
1
>>> s[s.duplicated(keep=False)]    # 加上引數keep=False,效果是隻保留所有重複的資料

Series轉DataFrame型別

Series物件就是一個一維陣列而已,是沒有列名屬性的,轉換成DataFrame物件加上列名

s.to_frame('列名')

根據指定列對兩個DataFrame進行相減處理去除重複行

有兩個DataFrame物件df1是完整資料,df2是一個Series轉換過來的DataFrame物件,其實就一列,現在想從df1中找出所有電話列=df2中資料的行刪除掉,得到期望結果

result = pd.concat([df1,df2], ignore_index=True, sort=False).drop_duplicates(subset='電話', keep=False)

對DataFrame分組後再隨機抽取行

 按照‘鄉鎮’列進行分組,然後每一組裡面隨機抽取500行資料

import pandas as pd
rnd_size = 500  #隨機抽取樣本數量
df = pd.read_csv('cmcc_all.csv')
result = df.groupby('鄉鎮').apply(lambda x: x.sample(rnd_size))
result.to_csv('隨機抽取結果.csv')
print('匯出完成')

分組統計

 對下面這張表按縣區進行分組,然後統計問題1~問題4各有多少個(計數)

縣區 問題1 問題2 問題3 問題4
湯陰 1 1 0 1
內黃 0 0 1
湯陰 1 0 0 1
湯陰 0 0 1
>>> df
   縣區  問題1  問題2  問題3  問題4
0  湯陰    1    1    0  1.0
1  內黃    0    0    1  NaN
2  湯陰    1    0    0  1.0
3  湯陰    0    0    1  NaN
>>> gp = df.groupby('縣區').count()
>>> gp
    問題1  問題2  問題3  問題4
縣區
內黃    1    1    1    0
湯陰    3    3    3    2
>>> gp = df.groupby('縣區').sum()
>>> gp
    問題1  問題2  問題3  問題4
縣區
內黃    0    0    1  0.0
湯陰    2    1    1  2.0

計數結果:

縣區 問題1 問題2 問題3 問題4
內黃 1 1 1 0
湯陰 3 3 3 2

實現Excel中Vlookup效果

df1 df2 result
A B A C A B C
10 Tom 9 Good 10 Tom Bad
11 Kate 10 Bad 11 Kate Good
12 Jack 11 Good 12 Jack Bad
13 Claire 12 Bad 13 Claire Bad
13 Bad

將df1和df2的A列進行關聯查詢,得到result中的結果 

>>> df1 = pd.DataFrame(columns=['A', 'B'], data=[[10,'Tom'],[11,'Kate'],[12,'Jack'],[13,'Claire']])
>>> df1
    A       B
0  10     Tom
1  11    Kate
2  12    Jack
3  13  Claire
>>> df2 = pd.DataFrame(columns=['A', 'C'], data=[[9,'Good'],[10,'Bad'],[11,'Good'],[12,'Bad'],[13,'Bad']])
>>> df2
    A     C
0   9  Good
1  10   Bad
2  11  Good
3  12   Bad
4  13   Bad
>>> result = df1.merge(df2, on='A', how='left')
>>> result
    A       B     C
0  10     Tom   Bad
1  11    Kate  Good
2  12    Jack   Bad
3  13  Claire   Bad

資料透檢視之堆疊(stack)分組統計例項

有這樣的原始資料:

xz q1 q2 q3
內黃 A B B
湯陰 A B B
水冶 B A A
滑縣 A B A
滑縣 C C C
滑縣 C C C
水冶 A A B

期望效果:以xz為index,分別對q1,q2,q3中可能出現的資料結果進行分列進行計數統計

q1 q2 q3
A B C A B C A B C
xz
內黃 1 1 1
水冶 1 1 2 1 1
湯陰 1 1 1
滑縣 1 2 1 2 1 2
>>> df = pd.read_excel('test.xlsx',sheet_name=1)    # 資料放在test.xlsx第二個工作簿裡面,故指定sheet_name=1(從0開始)
>>> df
   xz q1 q2 q3
0  內黃  A  B  B
1  湯陰  A  B  B
2  水冶  B  A  A
3  滑縣  A  B  A
4  滑縣  C  C  C
5  滑縣  C  C  C
6  水冶  A  A  B

>>> result = (df.set_index('xz')).groupby(level='xz').apply(lambda x: x.apply(pd.value_counts)).unstack(level=1).fillna(0)

# 分行解釋一下:
>>> result = (df.set_index('xz'))\    # 先設定index使用xz列
    .groupby(level='xz')\    # 以xz分組
    .apply(lambda x: x.apply(pd.value_counts))\    # 使用匿名函式lambda對數值進行計數統計
    .unstack(level=1)\    # 設定不堆疊
    .fillna(0)    # 對空置用0填充

>>> result.to_excel('result.xlsx')

------------------我是分割線------------------

上面的方法可以實現效果,但是如果q1~q3中可能存在的值不是都一樣是A,B,C這三種情況的話,比如說q1可能的值是A,B,C,而q2可能的值是X,Y,Z
這樣的話上述方法出來的結果就不對了,得用下面這種方法來構造,從stack overflow上面看的,具體每一步的解釋沒完全看懂,但是管用
原貼地址(https://stackoverflow.com/questions/44165629/pandas-pivot-table-for-multiple-columns-at-once)

 這種情況:

xz q1 q2 q3
內黃 A X B
湯陰 A X B
水冶 B Y A
滑縣 A Z A
滑縣 C Y C
滑縣 C X C
水冶 A Y B
# 如果還用剛才的方法來做的話,會把q1~q3中每一種可能出現的值都算成一列,就是這樣:

>>> result = (df.set_index('xz')).groupby(level='xz').apply(lambda x: x.apply(pd.value_counts)).unstack(level=1)

>>> result
     q1                        q2                          q3
      A    B    C   X   Y   Z   A   B   C    X    Y    Z    A    B    C   X   Y   Z
xz
內黃  1.0  NaN  NaN NaN NaN NaN NaN NaN NaN  1.0  NaN  NaN  NaN  1.0  NaN NaN NaN NaN
水冶  1.0  1.0  NaN NaN NaN NaN NaN NaN NaN  NaN  2.0  NaN  1.0  1.0  NaN NaN NaN NaN
湯陰  1.0  NaN  NaN NaN NaN NaN NaN NaN NaN  1.0  NaN  NaN  NaN  1.0  NaN NaN NaN NaN
滑縣  1.0  NaN  2.0 NaN NaN NaN NaN NaN NaN  1.0  1.0  1.0  1.0  NaN  2.0 NaN NaN NaN

# 所以應該用下面的方法來實現

>>> a = df.set_index('xz').stack().groupby(level=[0,1]).value_counts().unstack(level=[1,2]).sort_index(axis=1)

>>> a
     q1             q2             q3
      A    B    C    X    Y    Z    A    B    C
xz
內黃  1.0  NaN  NaN  1.0  NaN  NaN  NaN  1.0  NaN
水冶  1.0  1.0  NaN  NaN  2.0  NaN  1.0  1.0  NaN
湯陰  1.0  NaN  NaN  1.0  NaN  NaN  NaN  1.0  NaN
滑縣  1.0  NaN  2.0  1.0  1.0  1.0  1.0  NaN  2.0

自定義函式對指定列資料進行處理

現在有一個DataFrame df變數,其中有一列名為'電話',裡面的資料不太規矩,有的是空值,有的不是11位的手機號,現在需要將這些資料進行整理,通過自定義處理函式和apply(lambda)來實現:

import pandas as pd

df = pd.read_excel('1.xlsx')

# 自定義check函式,檢查傳入變數長度是否等於11位
def check(x):
    if len(str(x))!=11):
        return False
    else:
        return x


df['電話'].apply(lambda x: check(x))    # 這裡可以先檢視一下返回處理後的'電話'列中的資料

df['電話'] = df['電話'].apply(lambda x: check(x))    # 直接修改原df中的資料,將不合格資料替換為False

result = df[df['電話']!=False]    # 挑選出電話列合格的完整資料

# 附空值判斷:
df[df['鄉鎮'].isnull()]    # 挑選出鄉鎮列中是空值的完整行

df[df['鄉鎮'].notnull()]    # 挑選出鄉鎮列中不是空值的完整行