文章目錄
- 1. 生成dataframe
- 更改行索引的顯示順序:
- 更新列索引名:
- 2. 讀寫數據文件
- json:
- csv:
- txt:
- 3. 增加:
- 增加一列:
- 增加一行:
- 4. 刪除:
- 5. 更新
- 排序
- 分組
- 聚合
- 行索引變成外層索引,列索引變成內層索引
- 更新某個值
- 行索引重置
- 6. 顯示:
- 顯示一列
- 顯示多列
- 顯示一行:
- 顯示某個元素:
- 暴力法:
- 關于list與ndarray索引與切片的補充
- 查看某一行或者某一列有多少元素是1
- 條件篩選:
- 7. 數據缺失的處理:
- 8. 數據連接與合并:
- 連接
- 合并
- 9. 去重復
- 10.其它
- 提取數據,dataframe轉list
- 提取行索引
- 提取列索引
??這篇blog長期更新,總結一些python數據處理過程中常用的方法(不總結老是忘),我一般喜歡用dataframe做數據處理,所以一般會盡量轉成pandas的dataframe格式。所有方法需要先導入庫pandas和numpy。
import pandas as pd
import numpy as np
1. 生成dataframe
??pd.DataFrame
# 輸入二維向量,columns是列索引,index是行索引
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
print(df)
# 輸出:
"""
a b c
0 1 2 3
1 4 5 6
2 7 8 9
"""
更改行索引的顯示順序:
??df.reindex
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df = df.reindex([2,1,0])
print(df)
# 輸出
"""
a b c
2 7 8 9
1 4 5 6
0 1 2 3
"""
更新列索引名:
??df.columns
??df.rename
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
# 法一,暴力法
df.columns=['a', 'b', 'f']
# 法二,當列索引的數量很多,用第二種比較好,可以只改一部分
df.rename(columns={'b':'e'}, inplace = True)
print(df)
# 輸出
"""
a e f
0 1 2 3
1 4 5 6
2 7 8 9
"""
2. 讀寫數據文件
json:
# 讀取方法一,針對利用pd.to_json()存的json十分合適
pd.read_json('xxx')
# 讀取方法二,有時候讀取的json文件,不是由pd.to_json存的,利用pd.read_csv可能會有問題,要用這種方法
with open('xxx') as f:
for i in f.readlines():
data = json.load(i)
# 寫方法
pd.to_json('xxx')
csv:
# 讀方法,ignore_index用于確定是否保存行索引,ignore_index=False會保存行索引
pd.to_csv('xxx.csv', ignore_index=True)
# 寫方法,nrows用于選擇讀取前多少行,usecols用于選擇讀取哪些列
pd.read_csv('xxx.csv', nrows = 10000, usecols = [0, 5, 82, 83])
txt:
# 讀取
data=[]
f = open('xxx.txt', 'r')
for line in f:
info1, info2 = line.split(',') # 這里默認一行只有一個","來分割兩個數據,可以視情況增加輸出
data.append([info1, info2])
f.close
# 一般不建議保存成txt,可以直接保存成csv
3. 增加:
增加一列:
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df['d']=[4,7,10]
print(df)
# 輸出
"""
a b c d
0 1 2 3 4
1 4 5 6 7
2 7 8 9 10
"""
??如果增加一列,這一列是用已有的列計算出來的,注意如果原來的df中有’d’這一列,則會把數據替換掉。
??df.assign
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df = df.assign(d = lambda x: x.a+x.b) # a索引列與b索引列相加
print(df)
# 輸出
"""
a b c d
0 1 2 3 3
1 4 5 6 9
2 7 8 9 15
"""
??df.assign是一個十分強大的函數,下面給出一個更復雜的情況,把df的’a’列的元素向下移動一列放到’d’列中。
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
df.assign(d = lambda x: x.b.shift(1))
# 輸出
"""
a b c d
0 1 2 3 NaN
1 4 5 6 2.0
2 7 8 9 5.0
"""
??指定位置增加一列
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df.insert(1,'B',[11,12,13]) #列索引的1位置插入一列
print(df)
# 輸出
"""
a B b c
0 1 11 2 3
1 4 12 5 6
2 7 13 8 9
"""
增加一行:
??df.append
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df = df.append({'a':10, 'b':11, 'c':12}, ignore_index=True)
print(df)
# 輸出
"""
a b c
0 1 2 3
1 4 5 6
2 7 8 9
3 10 11 12
"""
4. 刪除:
??df.drop
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df.drop('a',axis=1, inplace=True) # axis=1刪除列,inplace為True表示直接對原表修改且返回None,默認是False
df = df.drop(0,axis=0) # axis=0刪除行
print(df)
# 輸出
"""
b c
1 5 6
2 8 9
"""
5. 更新
排序
??df.sort_values
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df = df.sort_values('b', ascending=False) # ascending=False表示降序排列
print(df)
# 輸出
"""
a b c
2 7 8 9
1 4 5 6
0 1 2 3
"""
??也可以根據多個元素進行排序,寫前面的優先考慮
df = pd.DataFrame([[1,2,3],[1,5,6],[2,5,9],[2,2,12]], columns=['a', 'b', 'c'], index = [0,1,2,3])
df = df.sort_values(['a', 'b'], ascending=False) # 先按照a列降序排,在a的基礎上,考慮b列的降序排
print(df)
# 輸出
"""
a b c
2 2 5 9
3 2 2 12
1 1 5 6
0 1 2 3
"""
??值得一提的是,這個排序方式也可以排序時間格式類似’2018-10-01 08:00:00’的時間數據。
分組
??df.groupby():分組,分組后輸出的是一個類,需要用for循環讀出。
df = pd.DataFrame([[1,2,3],[1,5,6],[7,8,9],[7,11,12]], columns=['a', 'b', 'c'])
for index, data in df.groupby(['a']):
print(index) # index是分組標簽值
print(data) # data是該分組下的dataframe數據
# 輸出
"""
1
a b c
0 1 2 3
1 1 5 6
7
a b c
2 7 8 9
3 7 11 12
"""
??當然也可以進行多列分組,只需向groupby()傳入一個含有多個元素的列表即可,同排序類似,寫在前面的優先級高。
??一般df.groupby()后,會接一個函數,例如count(),sum()等。
df = pd.DataFrame([[1,2,3],[1,5,6],[7,8,9],[7,11,12]], columns=['a', 'b', 'c'])
print(df.groupby(['a'], as_index=False).count())
# 輸出
"""
a b c
0 1 2 2 # b,c列的元素,表示分到a的每一個分組中的記錄個數
1 7 2 2
"""
df = pd.DataFrame([[1,2,3],[1,5,6],[7,8,9],[7,11,12]], columns=['a', 'b', 'c'])
print(df.groupby(['a'], as_index=False).sum())
# 輸出
"""
a b c
a b c
0 1 7 9 # b,c列的元素,表示分到a的每一個分組中的記錄,對應的b,c值的和
1 7 19 21
"""
聚合
??df.agg()一般在分組groupby()后進行,可以把我們想要觀察的指標,寫入一個列表[‘min’, ‘mean’, ‘max’, n0],n0是自定義的,出入agg()。
def n0(x): return sum(x==8) # 計算等于8的個數
df = pd.DataFrame([[1,2,3],[1,5,6],[7,8,9],[7,11,12]], columns=['a', 'b', 'c'])
print(df.groupby(['a'], as_index=False).agg(['min', 'mean', 'max', n0]))
# 輸出
"""
b c
min mean max n0 min mean max n0
a
1 2 3.5 5 0 3 4.5 6 0 # 在a=1的分組中,b,c的最小值、平均值、最大值、等于8的個數
7 8 9.5 11 1 9 10.5 12 0
"""
行索引變成外層索引,列索引變成內層索引
??df.stack()
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df.loc[1,'b'] = 'a'
df.stack()
# 輸出
"""
0 a 1
b 2
c 3
1 a 4
b a
c 6
2 a 7
b 8
c 9
dtype: object
"""
更新某個值
??df.loc
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df.loc[1,'b'] = 'a'
print(df)
# 輸出
"""
a b c
0 1 2 3
1 4 a 6
2 7 8 9
"""
行索引重置
??df.reset_index(drop=True)
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index=[1,2,3])
df = df.reset_index(drop=True)
print(df)
# 輸出
"""
a b c
0 1 2 3
1 4 5 6
2 7 8 9
"""
6. 顯示:
顯示一列
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
# 法一 輸出series
print(df['a']) # series
# 輸出
"""
0 1
1 4
2 7
Name: a, dtype: int64
"""
# 法二 輸出dataframe
print(df[['a']])
"""
a
0 1
1 4
2 7
"""
# 法三
print(df.a)
# 輸出
"""
0 1
1 4
2 7
Name: a, dtype: int64
"""
顯示多列
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
print(df[['a', 'b']])
# 輸出
"""
a b
0 1 2
1 4 5
2 7 8
"""
顯示一行:
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
print(df.loc[0])
# 輸出
"""
a 1
b 2
c 3
Name: 0, dtype: int64
"""
顯示某個元素:
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
print(df.loc[1, 'b'])
# 輸出
"""
5
"""
暴力法:
??利用df.iloc[],把dataframe完全當做二維ndarray進行索引,切片。
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
print(df.iloc[1, :])
# 輸出
"""
a 4
b 5
c 6
Name: 1, dtype: int64
"""
關于list與ndarray索引與切片的補充
注意二維list是不能進行二維切片,例如list[1, :]這樣的切片,二維ndarray是可以的,因為list的一個[]中不能存在多維索引,ndarray可以 ,具體看下面的例子。
a = [[1,2,3],[4,5,6]]
np_a = np.asarray(a)
a[1][1] # 可以
np_a[1][1] # 可以
a[1,1] # 報錯
np_a[1,1] # 可以,同np_a[1][1]
a[1][:] # 可以
np_a[1][:] # 可以
a[1, :] # 報錯
np_a[1, :] # 可以,同np_a[1][:]
查看某一行或者某一列有多少元素是1
df = pd.DataFrame([[1,2,3],[1,5,6],[2,5,9],[2,2,12]], columns=['a', 'b', 'c'], index = [0,1,2,3])
def n0(x): return sum(x==1) # 計算等于1的個數
df.apply(n0, axis=0) # 對行或者列執行n0,axis=0是按列,有點像spark那樣一個一個的計算
# 輸出
"""
a 2
b 0
c 0
dtype: int64
"""
條件篩選:
df = pd.DataFrame([[1,2,3],[4,5,6],[7,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2,3])
print(df[df['b']==5])
# 輸出
"""
a b c
1 4 5 6
2 7 5 6
"""
如果要同時滿足多個條件,要用&鏈接,同時加上(),不能用and鏈接 ,不然會報錯:ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
df = pd.DataFrame([[1,2,3],[4,5,6],[7,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2,3])
print(df[(df['b']==5) & (df['a']==4)])
# 輸出
"""
a b c
1 4 5 6
"""
找出某一列的最大值的行列索引
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
print(df.loc[lambda x: x.a==max(x.a),'a'])
# 輸出
"""
2 7
Name: a, dtype: int64
"""
可以把lambda中的x就理解為df自己,和spark中的用法不太一樣,spark的lambda中的x一般理解為一行。
7. 數據缺失的處理:
??注意,缺失值的表示是np.nan(或np.NaN),不是None。np.nan是沒有可比性的,看下面的代碼
print(np.nan == np.nan) # 輸出False
??想要單獨判斷np.nan,需要使用方法np.isnan()
np.isnan(np.NaN) # 輸出True
??但是None是有可比性的
print(None == None) # 輸出True
??如果利用pd.read_csv等讀取數據,存在缺失值時,會使用np.nan填充的,我們可以利用下面的方法進行缺失值判斷。
df = pd.DataFrame([[1,2,3],[np.NaN,5,6],[7,None,9]], columns=['a', 'b', 'c'])
print(df.isnull())
# 輸出
"""
a b c
0 False False False
1 True False False
2 False True False
"""
??可以看出來,其實 np.nan與None都會被當做缺失值處理的 ,但實際兩者是不一樣的。也可以單獨對某一列處理。
df = pd.DataFrame([[1,2,3],[np.NaN,5,6],[7,None,9]], columns=['a', 'b', 'c'])
print(df['a'].isnull())
print()
print(pd.isnull(df['a'])) # 與第二行一樣的效果
# 輸出
"""
0 False
1 True
2 False
Name: a, dtype: bool
0 False
1 True
2 False
Name: a, dtype: bool
"""
??我們可以用下面的方法對缺失值進行處理,仍然是同時處理np.nan與None。
# 刪掉含有缺失值的記錄
df = pd.DataFrame([[1,2,3],[np.NaN,5,6],[7,None,9]], columns=['a', 'b', 'c'])
print(df.dropna())
# 輸出
"""
a b c
0 1.0 2.0 3
"""
# 填補0
df = pd.DataFrame([[1,2,3],[np.NaN,5,6],[7,None,9]], columns=['a', 'b', 'c'])
print(df.fillna(0))
# 輸出
"""
a b c
0 1.0 2.0 3
1 0.0 5.0 6
2 7.0 0.0 9
"""
# 填補missing字樣
df = pd.DataFrame([[1,2,3],[np.NaN,5,6],[7,None,9]], columns=['a', 'b', 'c'])
print(df.fillna('missing'))
# 輸出
"""
a b c
0 1 2 3
1 missing 5 6
2 7 missing 9
"""
# 填補上一個數字
df = pd.DataFrame([[1,2,3],[np.NaN,5,6],[7,None,9]], columns=['a', 'b', 'c'])
print(df.fillna(method='pad'))
# 輸出
"""
a b c
0 1.0 2.0 3
1 1.0 5.0 6
2 7.0 5.0 9
"""
更多的方法可以看官方文檔:http://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.fillna.html
??當然,對于不同的情況,我們也許會設計不同的方法進行填充,甚至是特別復雜的方法。
8. 數據連接與合并:
連接
??pd.merge的功能同join差不多,可以實現內連接,左外鏈接,右外連接和全連接,對應的參數how={‘inner’, ‘left’, ‘right’, ‘outer’}。
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
df2 = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'd', 'f'])
output = pd.merge(df, df2, on='a', how='left') # df是左,df2是右
print(output)
# 輸出
"""
a b c d f
0 1 2 3 2 3
1 4 5 6 5 6
2 7 8 9 8 9
"""
??如果df與df2的用于連接的字段名字不一樣
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
df2 = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['d', 'e', 'f'])
output = pd.merge(df, df2, left_on='a', right_on='d', how='left').drop('d', axis=1) # 需要手動刪除重復的列
print(output)
# 輸出
"""
a b c e f
0 1 2 3 2 3
1 4 5 6 5 6
2 7 8 9 8 9
"""
??如果右邊出現用于連接的字段值重復的情況,會多次鏈接,以左鏈接為例,如下
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
df2 = pd.DataFrame([[1,2,3],[1,5,6],[7,8,9]], columns=['d', 'e', 'f'])
output = pd.merge(df, df2, left_on='a', right_on='d', how='left') # 這里沒有刪除d,所以下面會顯示d列
print(output)
# 輸出
"""
a b c d e f
0 1 2 3 1.0 2.0 3.0
1 1 2 3 1.0 5.0 6.0
2 4 5 6 NaN NaN NaN
3 7 8 9 7.0 8.0 9.0
"""
??所以在進行連接前,要構思好邏輯,可以加去重。
合并
??df2拼到df下面
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
df2 = pd.DataFrame([[1,2,3],[1,5,6],[7,8,9]], columns=['a', 'b', 'c'])
output = pd.concat([df, df2], ignore_index=True, axis=0) # axis=0,df2拼到df下面,ignore_index=True即把index重排
print(output)
# 輸出
"""
a b c
0 1 2 3
1 4 5 6
2 7 8 9
3 1 2 3
4 1 5 6
5 7 8 9
"""
??df2拼到df右面
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
df2 = pd.DataFrame([[1,2,3],[1,5,6],[7,8,9]], columns=['a', 'b', 'c'])
output = pd.concat([df, df2], ignore_index=True, axis=1) # ;axis=1,df2拼到df右面
print(output)
# 輸出
"""
0 1 2 3 4 5
0 1 2 3 1 2 3
1 4 5 6 1 5 6
2 7 8 9 7 8 9
"""
9. 去重復
??df.drop_duplicates().reset_index(drop=True)
df = pd.DataFrame([[1,2,3],[1,2,3],[7,8,9]], columns=['a', 'b', 'c'])
df = df.drop_duplicates().reset_index(drop=True)
print(df)
# 輸出
"""
a b c
0 1 2 3
1 7 8 9
"""
10.其它
提取數據,dataframe轉list
??df.values
df = pd.DataFrame([[1,2,3],[1,2,3],[7,8,9]], columns=['a', 'b', 'c'])
list_df = df.values
print(list_df)
# 輸出
"""
[[1 2 3]
[1 2 3]
[7 8 9]]
"""
提取行索引
??df.index
df = pd.DataFrame([[1,2,3],[1,2,3],[7,8,9]], columns=['a', 'b', 'c'])
for index in df.index:
print(index)
# 輸出
"""
0
1
2
"""
提取列索引
??df.columns
df = pd.DataFrame([[1,2,3],[1,2,3],[7,8,9]], columns=['a', 'b', 'c'])
for index in df.columns:
print(index)
# 輸出
"""
a
b
c
"""
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
