您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“Python Pandas的知識點有哪些”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
那么問題來了:
numpy已經(jīng)能夠幫助我們處理數(shù)據(jù),能夠結合matplotlib解決我們數(shù)據(jù)分析的問題,那么pandas學習的目的在什么地方呢?
numpy能夠幫我們處理處理數(shù)值型數(shù)據(jù),但是這還不夠, 很多時候,我們的數(shù)據(jù)除了數(shù)值之外,還有字符串,還有時間序列等
比如:我們通過爬蟲獲取到了存儲在數(shù)據(jù)庫中的數(shù)據(jù)
所以,pandas出現(xiàn)了。
Pandas的名稱來自于面板數(shù)據(jù)(panel data)
Pandas是一個強大的分析結構化數(shù)據(jù)的工具集,基于NumPy構建,提供了高級數(shù)據(jù)結構和數(shù)據(jù)操作工具,它是使Python成為強大而高效的數(shù)據(jù)分析環(huán)境的重要因素之一。
一個強大的分析和操作大型結構化數(shù)據(jù)集所需的工具集
基礎是NumPy,提供了高性能矩陣的運算
提供了大量能夠快速便捷地處理數(shù)據(jù)的函數(shù)和方法
應用于數(shù)據(jù)挖掘,數(shù)據(jù)分析
提供數(shù)據(jù)清洗功能
索引對象Index
示例代碼:
print(type(ser_obj.index))print(type(df_obj2.index))print(df_obj2.index)
運行結果:
<class 'pandas.indexes.range.RangeIndex'> <class 'pandas.indexes.numeric.Int64Index'> Int64Index([0, 1, 2, 3], dtype='int64')
示例代碼:
# 索引對象不可變df_obj2.index[0] = 2
運行結果:
---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-23-7f40a356d7d1> in <module>() 1 # 索引對象不可變----> 2 df_obj2.index[0] = 2/Users/Power/anaconda/lib/python3.6/site-packages/pandas/indexes/base.py in __setitem__(self, key, value) 1402 1403 def __setitem__(self, key, value):-> 1404 raise TypeError("Index does not support mutable operations") 1405 1406 def __getitem__(self, key):TypeError: Index does not support mutable operations
Index,索引
Int64Index,整數(shù)索引
MultiIndex,層級索引
DatetimeIndex,時間戳類型
示例代碼:
ser_obj = pd.Series(range(5), index = ['a', 'b', 'c', 'd', 'e'])print(ser_obj.head())
運行結果:
a 0 b 1 c 2 d 3 e 4 dtype: int64
ser_obj[‘label’], ser_obj[pos]
示例代碼:
# 行索引print(ser_obj['b'])print(ser_obj[2])
運行結果:
1 2
ser_obj[2:4], ser_obj[‘label1’: ’label3’]
注意,按索引名切片操作時,是包含終止索引的。
示例代碼:
# 切片索引print(ser_obj[1:3])print(ser_obj['b':'d'])
運行結果:
b 1 c 2 dtype: int64 b 1 c 2 d 3 dtype: int64
ser_obj[[‘label1’, ’label2’, ‘label3’]]
示例代碼:
# 不連續(xù)索引print(ser_obj[[0, 2, 4]])print(ser_obj[['a', 'e']])
運行結果:
a 0 c 2 e 4 dtype: int64 a 0 e 4 dtype: int64
示例代碼:
# 布爾索引ser_bool = ser_obj > 2print(ser_bool)print(ser_obj[ser_bool])print(ser_obj[ser_obj > 2])
運行結果:
a False b False c False d True e True dtype: bool d 3 e 4 dtype: int64 d 3 e 4 dtype: int64
示例代碼:
import numpy as np df_obj = pd.DataFrame(np.random.randn(5,4), columns = ['a', 'b', 'c', 'd'])print(df_obj.head())
運行結果:
a b c d 0 -0.241678 0.621589 0.843546 -0.383105 1 -0.526918 -0.485325 1.124420 -0.653144 2 -1.074163 0.939324 -0.309822 -0.209149 3 -0.716816 1.844654 -2.123637 -1.323484 4 0.368212 -0.910324 0.064703 0.486016
df_obj[[‘label’]]
示例代碼:
# 列索引print(df_obj['a']) # 返回Series類型
運行結果:
0 -0.241678 1 -0.526918 2 -1.074163 3 -0.716816 4 0.368212 Name: a, dtype: float64
df_obj[[‘label1’, ‘label2’]]
示例代碼:
# 不連續(xù)索引print(df_obj[['a','c']])
運行結果:
a c 0 -0.241678 0.843546 1 -0.526918 1.124420 2 -1.074163 -0.309822 3 -0.716816 -2.123637 4 0.368212 0.064703
Pandas的高級索引有3種
DataFrame 不能直接切片,可以通過loc來做切片
loc是基于標簽名的索引,也就是我們自定義的索引名
示例代碼:
# 標簽索引 loc# Seriesprint(ser_obj['b':'d'])print(ser_obj.loc['b':'d'])# DataFrameprint(df_obj['a'])# 第一個參數(shù)索引行,第二個參數(shù)是列print(df_obj.loc[0:2, 'a'])
運行結果:
b 1 c 2 d 3 dtype: int64 b 1 c 2 d 3 dtype: int64 0 -0.241678 1 -0.526918 2 -1.074163 3 -0.716816 4 0.368212 Name: a, dtype: float64 0 -0.241678 1 -0.526918 2 -1.074163 Name: a, dtype: float64
作用和loc一樣,不過是基于索引編號來索引
示例代碼:
# 整型位置索引 iloc# Seriesprint(ser_obj[1:3])print(ser_obj.iloc[1:3])# DataFrameprint(df_obj.iloc[0:2, 0]) # 注意和df_obj.loc[0:2, 'a']的區(qū)別
運行結果:
b 1 c 2 dtype: int64 b 1 c 2 dtype: int64 0 -0.241678 1 -0.526918 Name: a, dtype: float64
ix是以上二者的綜合,既可以使用索引編號,又可以使用自定義索引,要視情況不同來使用,
如果索引既有數(shù)字又有英文,那么這種方式是不建議使用的,容易導致定位的混亂。
示例代碼:
# 混合索引 ix# Seriesprint(ser_obj.ix[1:3])print(ser_obj.ix['b':'c'])# DataFrameprint(df_obj.loc[0:2, 'a'])print(df_obj.ix[0:2, 0])
運行結果:
b 1 c 2 dtype: int64 b 1 c 2 dtype: int64 0 -0.241678 1 -0.526918 2 -1.074163 Name: a, dtype: float64
注意
DataFrame索引操作,可將其看作ndarray的索引操作
標簽的切片索引是包含末尾位置的
Pandas的對齊運算是數(shù)據(jù)清洗的重要過程,可以按索引對齊進行運算,如果沒對齊的位置則補NaN,最后也可以填充NaN
示例代碼:
s1 = pd.Series(range(10, 20), index = range(10))s2 = pd.Series(range(20, 25), index = range(5))print('s1: ' )print(s1)print('') print('s2: ')print(s2)
運行結果:
s1: 0 10 1 11 2 12 3 13 4 14 5 15 6 16 7 17 8 18 9 19 dtype: int64 s2: 0 20 1 21 2 22 3 23 4 24 dtype: int64
示例代碼:
# Series 對齊運算s1 + s2
運行結果:
0 30.0 1 32.0 2 34.0 3 36.0 4 38.0 5 NaN 6 NaN 7 NaN 8 NaN 9 NaN dtype: float64
示例代碼:
df1 = pd.DataFrame(np.ones((2,2)), columns = ['a', 'b'])df2 = pd.DataFrame(np.ones((3,3)), columns = ['a', 'b', 'c'])print('df1: ')print(df1)print('') print('df2: ')print(df2)
運行結果:
df1: a b 0 1.0 1.0 1 1.0 1.0 df2: a b c 0 1.0 1.0 1.0 1 1.0 1.0 1.0 2 1.0 1.0 1.0
示例代碼:
# DataFrame對齊操作df1 + df2
運行結果:
a b c0 2.0 2.0 NaN1 2.0 2.0 NaN2 NaN NaN NaN
使用
add
,sub
,p
,mul
的同時,通過
fill_value
指定填充值,未對齊的數(shù)據(jù)將和填充值做運算
示例代碼:
print(s1)print(s2)s1.add(s2, fill_value = -1)print(df1)print(df2)df1.sub(df2, fill_value = 2.)
運行結果:
# print(s1)0 101 112 123 134 145 156 167 178 189 19dtype: int64# print(s2)0 201 212 223 234 24dtype: int64# s1.add(s2, fill_value = -1)0 30.01 32.02 34.03 36.04 38.05 14.06 15.07 16.08 17.09 18.0dtype: float64# print(df1) a b0 1.0 1.01 1.0 1.0# print(df2) a b c0 1.0 1.0 1.01 1.0 1.0 1.02 1.0 1.0 1.0# df1.sub(df2, fill_value = 2.) a b c0 0.0 0.0 1.01 0.0 0.0 1.02 1.0 1.0 1.0
算術方法表:
方法 | 描述 |
---|---|
add,radd | 加法(+) |
sub,rsub | 減法(-) |
p,rp | 除法(/) |
floorp,rfllorp | 整除(//) |
mul,rmul | 乘法(*) |
pow,rpow | 冪次方(**) |
示例代碼:
# Numpy ufunc 函數(shù)df = pd.DataFrame(np.random.randn(5,4) - 1)print(df)print(np.abs(df))
運行結果:
0 1 2 3 0 -0.062413 0.844813 -1.853721 -1.980717 1 -0.539628 -1.975173 -0.856597 -2.612406 2 -1.277081 -1.088457 -0.152189 0.530325 3 -1.356578 -1.996441 0.368822 -2.211478 4 -0.562777 0.518648 -2.007223 0.059411 0 1 2 3 0 0.062413 0.844813 1.853721 1.980717 1 0.539628 1.975173 0.856597 2.612406 2 1.277081 1.088457 0.152189 0.530325 3 1.356578 1.996441 0.368822 2.211478 4 0.562777 0.518648 2.007223 0.059411
示例代碼:
# 使用apply應用行或列數(shù)據(jù)#f = lambda x : x.max()print(df.apply(lambda x : x.max()))
運行結果:
0 -0.062413 1 0.844813 2 0.368822 3 0.530325 dtype: float64
注意指定軸的方向,默認axis=0,方向是列
示例代碼:
# 指定軸方向,axis=1,方向是行print(df.apply(lambda x : x.max(), axis=1))
運行結果:
0 0.844813 1 -0.539628 2 0.530325 3 0.368822 4 0.518648 dtype: float64
示例代碼:
# 使用applymap應用到每個數(shù)據(jù)f2 = lambda x : '%.2f' % xprint(df.applymap(f2))
運行結果:
0 1 2 3 0 -0.06 0.84 -1.85 -1.98 1 -0.54 -1.98 -0.86 -2.61 2 -1.28 -1.09 -0.15 0.53 3 -1.36 -2.00 0.37 -2.21 4 -0.56 0.52 -2.01 0.06
sort_index()
排序默認使用升序排序,ascending=False 為降序排序
示例代碼:
# Seriess4 = pd.Series(range(10, 15), index = np.random.randint(5, size=5))print(s4)# 索引排序s4.sort_index() # 0 0 1 3 3
運行結果:
0 10 3 11 1 12 3 13 0 14 dtype: int64 0 10 0 14 1 12 3 11 3 13 dtype: int64
對DataFrame操作時注意軸方向
示例代碼:
# DataFramedf4 = pd.DataFrame(np.random.randn(3, 5), index=np.random.randint(3, size=3), columns=np.random.randint(5, size=5))print(df4)df4_isort = df4.sort_index(axis=1, ascending=False)print(df4_isort) # 4 2 1 1 0
運行結果:
1 4 0 1 2 2 -0.416686 -0.161256 0.088802 -0.004294 1.164138 1 -0.671914 0.531256 0.303222 -0.509493 -0.342573 1 1.988321 -0.466987 2.787891 -1.105912 0.889082 4 2 1 1 0 2 -0.161256 1.164138 -0.416686 -0.004294 0.088802 1 0.531256 -0.342573 -0.671914 -0.509493 0.303222 1 -0.466987 0.889082 1.988321 -1.105912 2.787891
sort_values(by=‘column name’)
根據(jù)某個唯一的列名進行排序,如果有其他相同列名則報錯。
示例代碼:
# 按值排序df4_vsort = df4.sort_values(by=0, ascending=False)print(df4_vsort)
運行結果:
1 4 0 1 2 1 1.988321 -0.466987 2.787891 -1.105912 0.889082 1 -0.671914 0.531256 0.303222 -0.509493 -0.342573 2 -0.416686 -0.161256 0.088802 -0.004294 1.164138
示例代碼:
df_data = pd.DataFrame([np.random.randn(3), [1., 2., np.nan], [np.nan, 4., np.nan], [1., 2., 3.]])print(df_data.head())
運行結果:
0 1 2 0 -0.281885 -0.786572 0.487126 1 1.000000 2.000000 NaN 2 NaN 4.000000 NaN 3 1.000000 2.000000 3.000000
示例代碼:
# isnullprint(df_data.isnull())
運行結果:
0 1 2 0 False False False 1 False False True 2 True False True 3 False False False
根據(jù)axis軸方向,丟棄包含NaN的行或列。 示例代碼:
# dropnaprint(df_data.dropna()) # 默認是按行print(df_data.dropna(axis=1)) # axis=1是按列
運行結果:
0 1 2 0 -0.281885 -0.786572 0.487126 3 1.000000 2.000000 3.000000 1 0 -0.786572 1 2.000000 2 4.000000 3 2.000000
示例代碼:
# fillnaprint(df_data.fillna(-100.))
運行結果:
0 1 2 0 -0.281885 -0.786572 0.487126 1 1.000000 2.000000 -100.000000 2 -100.000000 4.000000 -100.000000 3 1.000000 2.000000 3.000000
下面創(chuàng)建一個Series, 在輸入索引Index時,輸入了由兩個子list組成的list,第一個子list是外層索引,第二個list是內(nèi)層索引。
示例代碼:
import pandas as pdimport numpy as np ser_obj = pd.Series(np.random.randn(12),index=[ ['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'd'], [0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2] ])print(ser_obj)
運行結果:
a 0 0.099174 1 -0.310414 2 -0.558047 b 0 1.742445 1 1.152924 2 -0.725332 c 0 -0.150638 1 0.251660 2 0.063387 d 0 1.080605 1 0.567547 2 -0.154148 dtype: float64
打印這個Series的索引類型,顯示是MultiIndex
直接將索引打印出來,可以看到有l(wèi)avels,和labels兩個信息。levels表示兩個層級中分別有那些標簽,labels是每個位置分別是什么標簽。
示例代碼:
print(type(ser_obj.index))print(ser_obj.index)
運行結果:
<class 'pandas.indexes.multi.MultiIndex'>MultiIndex(levels=[['a', 'b', 'c', 'd'], [0, 1, 2]], labels=[[0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3], [0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2]])
根據(jù)索引獲取數(shù)據(jù)。因為現(xiàn)在有兩層索引,當通過外層索引獲取數(shù)據(jù)的時候,可以直接利用外層索引的標簽來獲取。
當要通過內(nèi)層索引獲取數(shù)據(jù)的時候,在list中傳入兩個元素,前者是表示要選取的外層索引,后者表示要選取的內(nèi)層索引。
ser_obj[‘outer_label’]
示例代碼:
# 外層選取print(ser_obj['c'])
運行結果:
0 -1.362096 1 1.558091 2 -0.452313 dtype: float64
ser_obj[:, ‘inner_label’]
示例代碼:
# 內(nèi)層選取print(ser_obj[:, 2])
運行結果:
a 0.826662 b 0.015426 c -0.452313 d -0.051063 dtype: float64
常用于分組操作、透視表的生成等
.swaplevel( )交換內(nèi)層與外層索引。
示例代碼:
print(ser_obj.swaplevel())
運行結果:
0 a 0.099174 1 a -0.310414 2 a -0.558047 0 b 1.742445 1 b 1.152924 2 b -0.725332 0 c -0.150638 1 c 0.251660 2 c 0.063387 0 d 1.080605 1 d 0.567547 2 d -0.154148 dtype: float64
.sortlevel( )先對外層索引進行排序,再對內(nèi)層索引進行排序,默認是升序。
示例代碼:
# 交換并排序分層print(ser_obj.swaplevel().sortlevel())
運行結果:
0 a 0.099174 b 1.742445 c -0.150638 d 1.080605 1 a -0.310414 b 1.152924 c 0.251660 d 0.567547 2 a -0.558047 b -0.725332 c 0.063387 d -0.154148 dtype: float64
示例代碼:
arr1 = np.random.rand(4,3)pd1 = pd.DataFrame(arr1,columns=list('ABC'),index=list('abcd'))f = lambda x: '%.2f'% x pd2 = pd1.applymap(f).astype(float)pd2
運行結果:
A B C a 0.87 0.26 0.67 b 0.69 0.89 0.17 c 0.94 0.33 0.04 d 0.35 0.46 0.29
axis=0 按列統(tǒng)計,axis=1按行統(tǒng)計
skipna 排除缺失值, 默認為True
示例代碼:
pd2.sum() #默認把這一列的Series計算,所有行求和pd2.sum(axis='columns') #指定求每一行的所有列的和pd2.idxmax()#查看每一列所有行的最大值所在的標簽索引,同樣我們也可以通過axis='columns'求每一行所有列的最大值的標簽索引
運行結果:
A 2.85 B 1.94 C 1.17 dtype: float64 a 1.80 b 1.75 c 1.31 d 1.10 dtype: float64 A c B b C a dtype: object
示例代碼:
pd2.describe()#查看匯總
運行結果:
A B C count 4.000000 4.00000 4.000000mean 0.712500 0.48500 0.292500std 0.263613 0.28243 0.271585min 0.350000 0.26000 0.04000025% 0.605000 0.31250 0.13750050% 0.780000 0.39500 0.23000075% 0.887500 0.56750 0.385000max 0.940000 0.89000 0.670000
#百分比:除以原來的量pd2.pct_change() #查看行的百分比變化,同樣指定axis='columns'列與列的百分比變化 A B C a NaN NaN NaN b -0.206897 2.423077 -0.746269c 0.362319 -0.629213 -0.764706d -0.627660 0.393939 6.250000
讀取csv文件read_csv
(file_path or buf,usecols,encoding):file_path
:文件路徑,usecols
:指定讀取的列名,encoding
:編碼
data = pd.read_csv('d:/test_data/food_rank.csv',encoding='utf8')data.head() name num0 酥油茶 219.01 青稞酒 95.02 酸奶 62.03 糌粑 16.04 琵琶肉 2.0#指定讀取的列名data = pd.read_csv('d:/test_data/food_rank.csv',usecols=['name'])data.head() name0 酥油茶1 青稞酒2 酸奶3 糌粑4 琵琶肉#如果文件路徑有中文,則需要知道參數(shù)engine='python'data = pd.read_csv('d:/數(shù)據(jù)/food_rank.csv',engine='python',encoding='utf8')data.head() name num0 酥油茶 219.01 青稞酒 95.02 酸奶 62.03 糌粑 16.04 琵琶肉 2.0#建議文件路徑和文件名,不要出現(xiàn)中文
寫入csv文件
DataFrame:to_csv
(file_path or buf,sep,columns,header,index,na_rep,mode):file_path
:保存文件路徑,默認None,sep
:分隔符,默認’,’ ,columns
:是否保留某列數(shù)據(jù),默認None,header
:是否保留列名,默認True,index
:是否保留行索引,默認True,na_rep
:指定字符串來代替空值,默認是空字符,mode
:默認’w’,追加’a’
**Series**:`Series.to_csv`\ (_path=None_,_index=True_,_sep='_,_'_,_na\_rep=''_,_header=False_,_mode='w'_,_encoding=None_\)
pandas
sqlalchemy
pymysql
# 導入必要模塊import pandas as pdfrom sqlalchemy import create_engine#初始化數(shù)據(jù)庫連接#用戶名root 密碼 端口 3306 數(shù)據(jù)庫 db2engine = create_engine('mysql+pymysql://root:@localhost:3306/db2')#查詢語句sql = ''' select * from class; '''#兩個參數(shù) sql語句 數(shù)據(jù)庫連接df = pd.read_sql(sql,engine)df
#新建df = pd.DataFrame({'id':[1,2,3,4],'num':[34,56,78,90]})df = pd.read_csv('ex1.csv')# #寫入到數(shù)據(jù)庫df.to_sql('df2',engine,index=False)print("ok")
進入數(shù)據(jù)庫查看
數(shù)據(jù)清洗是數(shù)據(jù)分析關鍵的一步,直接影響之后的處理工作
數(shù)據(jù)需要修改嗎?有什么需要修改的嗎?數(shù)據(jù)應該怎么調整才能適用于接下來的分析和挖掘?
是一個迭代的過程,實際項目中可能需要不止一次地執(zhí)行這些清洗操作
pd.fillna()
pd.dropna()
duplicated\(\)
: 返回布爾型Series表示每行是否為重復行
示例代碼:
import numpy as npimport pandas as pd df_obj = pd.DataFrame({'data1' : ['a'] * 4 + ['b'] * 4, 'data2' : np.random.randint(0, 4, 8)})print(df_obj)print(df_obj.duplicated())
運行結果:
# print(df_obj) data1 data20 a 31 a 22 a 33 a 34 b 15 b 06 b 37 b 0# print(df_obj.duplicated())0 False1 False2 True3 True4 False5 False6 False7 Truedtype: bool
默認判斷全部列
可指定按某些列判斷
示例代碼:
print(df_obj.drop_duplicates())print(df_obj.drop_duplicates('data2'))
運行結果:
# print(df_obj.drop_duplicates()) data1 data20 a 31 a 24 b 15 b 06 b 3# print(df_obj.drop_duplicates('data2')) data1 data20 a 31 a 24 b 15 b 0
根據(jù)map傳入的函數(shù)對每行或每列進行轉換
示例代碼:
ser_obj = pd.Series(np.random.randint(0,10,10))print(ser_obj)print(ser_obj.map(lambda x : x ** 2))
運行結果:
# print(ser_obj)0 11 42 83 64 85 66 67 48 79 3dtype: int64# print(ser_obj.map(lambda x : x ** 2))0 11 162 643 364 645 366 367 168 499 9dtype: int64
示例代碼:
# 單個值替換單個值print(ser_obj.replace(1, -100))# 多個值替換一個值print(ser_obj.replace([6, 8], -100))# 多個值替換多個值print(ser_obj.replace([4, 7], [-100, -200]))
運行結果:
# print(ser_obj.replace(1, -100))0 -1001 42 83 64 85 66 67 48 79 3dtype: int64# print(ser_obj.replace([6, 8], -100))0 11 42 -1003 -1004 -1005 -1006 -1007 48 79 3dtype: int64# print(ser_obj.replace([4, 7], [-100, -200]))0 11 -1002 83 64 85 66 67 -1008 -2009 3dtype: int64
根據(jù)單個或多個鍵將不同DataFrame的行連接起來
類似數(shù)據(jù)庫的連接操作
pd.merge:(left, right, how=‘inner’,on=None,left_on=None, right_on=None )
left:合并時左邊的DataFrame
right:合并時右邊的DataFrame
how:合并的方式,默認’inner’, ‘outer’, ‘left’, ‘right’
on:需要合并的列名,必須兩邊都有的列名,并以 left 和 right 中的列名的交集作為連接鍵
left_on: left Dataframe中用作連接鍵的列
right_on: right Dataframe中用作連接鍵的列
內(nèi)連接 inner:對兩張表都有的鍵的交集進行聯(lián)合
全連接 outer:對兩者表的都有的鍵的并集進行聯(lián)合
左連接 left:對所有左表的鍵進行聯(lián)合
右連接 right:對所有右表的鍵進行聯(lián)合
示例代碼:
import pandas as pdimport numpy as np left = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'], 'A': ['A0', 'A1', 'A2', 'A3'], 'B': ['B0', 'B1', 'B2', 'B3']})right = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'], 'C': ['C0', 'C1', 'C2', 'C3'], 'D': ['D0', 'D1', 'D2', 'D3']})pd.merge(left,right,on='key') #指定連接鍵key
運行結果:
key A B C D0 K0 A0 B0 C0 D01 K1 A1 B1 C1 D12 K2 A2 B2 C2 D23 K3 A3 B3 C3 D3
示例代碼:
left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'], 'key2': ['K0', 'K1', 'K0', 'K1'], 'A': ['A0', 'A1', 'A2', 'A3'], 'B': ['B0', 'B1', 'B2', 'B3']})right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'], 'key2': ['K0', 'K0', 'K0', 'K0'], 'C': ['C0', 'C1', 'C2', 'C3'], 'D': ['D0', 'D1', 'D2', 'D3']})pd.merge(left,right,on=['key1','key2']) #指定多個鍵,進行合并
運行結果:
key1 key2 A B C D0 K0 K0 A0 B0 C0 D01 K1 K0 A2 B2 C1 D12 K1 K0 A2 B2 C2 D2
#指定左連接left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'], 'key2': ['K0', 'K1', 'K0', 'K1'], 'A': ['A0', 'A1', 'A2', 'A3'], 'B': ['B0', 'B1', 'B2', 'B3']})right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'], 'key2': ['K0', 'K0', 'K0', 'K0'], 'C': ['C0', 'C1', 'C2', 'C3'], 'D': ['D0', 'D1', 'D2', 'D3']})pd.merge(left, right, how='left', on=['key1', 'key2']) key1 key2 A B C D0 K0 K0 A0 B0 C0 D01 K0 K1 A1 B1 NaN NaN2 K1 K0 A2 B2 C1 D13 K1 K0 A2 B2 C2 D24 K2 K1 A3 B3 NaN NaN
#指定右連接left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'], 'key2': ['K0', 'K1', 'K0', 'K1'], 'A': ['A0', 'A1', 'A2', 'A3'], 'B': ['B0', 'B1', 'B2', 'B3']})right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'], 'key2': ['K0', 'K0', 'K0', 'K0'], 'C': ['C0', 'C1', 'C2', 'C3'], 'D': ['D0', 'D1', 'D2', 'D3']})pd.merge(left, right, how='right', on=['key1', 'key2']) key1 key2 A B C D0 K0 K0 A0 B0 C0 D01 K1 K0 A2 B2 C1 D12 K1 K0 A2 B2 C2 D23 K2 K0 NaN NaN C3 D3
默認是“內(nèi)連接”(inner),即結果中的鍵是交集
how
: 指定連接方式
“外連接”(outer),結果中的鍵是并集
示例代碼:
left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'], 'key2': ['K0', 'K1', 'K0', 'K1'], 'A': ['A0', 'A1', 'A2', 'A3'], 'B': ['B0', 'B1', 'B2', 'B3']})right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'], 'key2': ['K0', 'K0', 'K0', 'K0'], 'C': ['C0', 'C1', 'C2', 'C3'], 'D': ['D0', 'D1', 'D2', 'D3']}) pd.merge(left,right,how='outer',on=['key1','key2'])
運行結果:
key1 key2 A B C D0 K0 K0 A0 B0 C0 D01 K0 K1 A1 B1 NaN NaN2 K1 K0 A2 B2 C1 D13 K1 K0 A2 B2 C2 D24 K2 K1 A3 B3 NaN NaN5 K2 K0 NaN NaN C3 D3
參數(shù)suffixes:默認為_x, _y
示例代碼:
# 處理重復列名df_obj1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'], 'data' : np.random.randint(0,10,7)})df_obj2 = pd.DataFrame({'key': ['a', 'b', 'd'], 'data' : np.random.randint(0,10,3)})print(pd.merge(df_obj1, df_obj2, on='key', suffixes=('_left', '_right')))
運行結果:
data_left key data_right0 9 b 11 5 b 12 1 b 13 2 a 84 2 a 85 5 a 8
參數(shù)left_index=True或right_index=True
示例代碼:
# 按索引連接df_obj1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'], 'data1' : np.random.randint(0,10,7)})df_obj2 = pd.DataFrame({'data2' : np.random.randint(0,10,3)}, index=['a', 'b', 'd'])print(pd.merge(df_obj1, df_obj2, left_on='key', right_index=True))
運行結果:
data1 key data20 3 b 61 4 b 66 8 b 62 6 a 04 3 a 05 0 a 0
沿軸方向將多個對象合并到一起
np.concatenate
示例代碼:
import numpy as npimport pandas as pd arr1 = np.random.randint(0, 10, (3, 4))arr2 = np.random.randint(0, 10, (3, 4))print(arr1)print(arr2)print(np.concatenate([arr1, arr2])) # 默認axis=0,按行拼接print(np.concatenate([arr1, arr2], axis=1)) # 按列拼接
運行結果:
# print(arr1)[[3 3 0 8] [2 0 3 1] [4 8 8 2]]# print(arr2)[[6 8 7 3] [1 6 8 7] [1 4 7 1]]# print(np.concatenate([arr1, arr2])) [[3 3 0 8] [2 0 3 1] [4 8 8 2] [6 8 7 3] [1 6 8 7] [1 4 7 1]]# print(np.concatenate([arr1, arr2], axis=1)) [[3 3 0 8 6 8 7 3] [2 0 3 1 1 6 8 7] [4 8 8 2 1 4 7 1]]
注意指定軸方向,默認axis=0
join指定合并方式,默認為outer
Series合并時查看行索引有無重復
df1 = pd.DataFrame(np.arange(6).reshape(3,2),index=list('abc'),columns=['one','two'])df2 = pd.DataFrame(np.arange(4).reshape(2,2)+5,index=list('ac'),columns=['three','four'])pd.concat([df1,df2]) #默認外連接,axis=0 four one three two a NaN 0.0 NaN 1.0b NaN 2.0 NaN 3.0c NaN 4.0 NaN 5.0a 6.0 NaN 5.0 NaN c 8.0 NaN 7.0 NaN pd.concat([df1,df2],axis='columns') #指定axis=1連接 one two three four a 0 1 5.0 6.0b 2 3 NaN NaN c 4 5 7.0 8.0#同樣我們也可以指定連接的方式為innerpd.concat([df1,df2],axis=1,join='inner') one two three four a 0 1 5 6c 4 5 7 8
將列索引旋轉為行索引,完成層級索引
DataFrame->Series
示例代碼:
import numpy as npimport pandas as pd df_obj = pd.DataFrame(np.random.randint(0,10, (5,2)), columns=['data1', 'data2'])print(df_obj)stacked = df_obj.stack()print(stacked)
運行結果:
# print(df_obj) data1 data20 7 91 7 82 8 93 4 14 1 2# print(stacked)0 data1 7 data2 91 data1 7 data2 82 data1 8 data2 93 data1 4 data2 14 data1 1 data2 2dtype: int64
將層級索引展開
Series->DataFrame
默認操作內(nèi)層索引,即level=-1
示例代碼:
# 默認操作內(nèi)層索引print(stacked.unstack())# 通過level指定操作索引的級別print(stacked.unstack(level=0))
運行結果:
# print(stacked.unstack()) data1 data20 7 91 7 82 8 93 4 14 1 2# print(stacked.unstack(level=0)) 0 1 2 3 4data1 7 7 8 4 1data2 9 8 9 1 2
什么是分組聚合?如圖:
groupby:(by=None,as_index=True)
by:根據(jù)什么進行分組,用于確定groupby的組
as_index:對于聚合輸出,返回以組便簽為索引的對象,僅對DataFrame
df1 = pd.DataFrame({'fruit':['apple','banana','orange','apple','banana'], 'color':['red','yellow','yellow','cyan','cyan'], 'price':[8.5,6.8,5.6,7.8,6.4]})#查看類型type(df1.groupby('fruit'))pandas.core.groupby.groupby.DataFrameGroupBy #GruopBy對象,它是一個包含組名,和數(shù)據(jù)塊的2維元組序列,支持迭代for name, group in df1.groupby('fruit'): print(name) #輸出組名 apple banana orange print(group) # 輸出數(shù)據(jù)塊 fruit color price 0 apple red 8.5 3 apple cyan 7.8 fruit color price 1 banana yellow 6.8 4 banana cyan 6.4 fruit color price 2 orange yellow 5.6 #輸出group類型 print(type(group)) #數(shù)據(jù)塊是dataframe類型 <class 'pandas.core.frame.DataFrame'> <class 'pandas.core.frame.DataFrame'> <class 'pandas.core.frame.DataFrame'>#選擇任意的數(shù)據(jù)塊dict(list(df1.groupby('fruit')))['apple'] #取出apple組的數(shù)據(jù)塊 fruit color price0 apple red 8.53 apple cyan 7.8
聚合
函數(shù)名 | 描述 |
---|---|
count | 分組中非NA值的數(shù)量 |
sum | 非NA值的和 |
mean | 非NA值的平均值 |
median | 非NA值的中位數(shù) |
std, var | 標準差和方差 |
min, max | 非NA的最小值,最大值 |
prod | 非NA值的乘積 |
first, last | 非NA值的第一個,最后一個 |
#Groupby對象具有上表中的聚合方法#根據(jù)fruit來求price的平均值df1['price'].groupby(df1['fruit']).mean()fruit apple 8.15banana 6.60orange 5.60Name: price, dtype: float64 #或者df1.groupby('fruit')['price'].mean()# as_index=False(不把分組后的值作為索引,重新生成默認索引)df1.groupby('fruit',as_index=False)['price'].mean() fruit price0 apple 8.151 banana 6.602 orange 5.60""" 如果我現(xiàn)在有個需求,計算每種水果的差值, 1.上表中的聚合函數(shù)不能滿足于我們的需求,我們需要使用自定義的聚合函數(shù) 2.在分組對象中,使用我們自定義的聚合函數(shù) """#定義一個計算差值的函數(shù)def diff_value(arr): return arr.max() - arr.min()#使用自定義聚合函數(shù),我們需要將函數(shù)傳遞給agg或aggregate方法,我們使用自定義聚合函數(shù)時,會比我們表中的聚合函數(shù)慢的多,因為要進行函數(shù)調用,數(shù)據(jù)重新排列df1.groupby('fruit')['price'].agg(diff_value)fruit apple 0.7banana 0.4orange 0.0Name: price, dtype: float64
通過字典或Series對象進行分組:
m = {'a':'red', 'b':'blue'}people.groupby(m, axis=1).sum()s1 = pd.Series(m)people.groupby(s1, axis=1).sum()
通過函數(shù)進行分組:
people.groupyby(len).sum()
時間序列(time series)數(shù)據(jù)是一種重要的結構化數(shù)據(jù)形式。
在多個時間點觀察或測量到的任何時間都可以形成一段時間序列。很多時間, 時間序列是固定頻率的, 也就是說, 數(shù)據(jù)點是根據(jù)某種規(guī)律定期出現(xiàn)的(比如每15秒…)。
時間序列也可以是不定期的。時間序列數(shù)據(jù)的意義取決于具體的應用場景。
主要由以下幾種:
時間戳(timestamp),特定的時刻。
固定時期(period),如2007年1月或2010年全年。
時間間隔(interval),由起始和結束時間戳表示。時期(period)可以被看做間隔(interval)的特例。
Python標準庫包含用于日期(date)和時間(time)數(shù)據(jù)的數(shù)據(jù)類型,而且還有日歷方面的功能。我們主要會用到datetime
、time
以及calendar
模塊。
datetime.datetime
(也可以簡寫為datetime)是用得最多的數(shù)據(jù)類型:
In [10]: from datetime import datetime In [11]: now = datetime.now()In [12]: now Out[12]: datetime.datetime(2017, 9, 25, 14, 5, 52, 72973)In [13]: now.year, now.month, now.day Out[13]: (2017, 9, 25)
datetime
以毫秒形式存儲日期和時間。timedelta表示兩個datetime對象之間的時間差:
In [14]: delta = datetime(2011, 1, 7) - datetime(2008, 6, 24, 8, 15)In [15]: delta Out[15]: datetime.timedelta(926, 56700)In [16]: delta.days Out[16]: 926In [17]: delta.seconds Out[17]: 56700
可以給datetime對象加上(或減去)一個或多個timedelta,這樣會產(chǎn)生一個新對象:
In [18]: from datetime import timedelta In [19]: start = datetime(2011, 1, 7)In [20]: start + timedelta(12)Out[20]: datetime.datetime(2011, 1, 19, 0, 0)In [21]: start - 2 * timedelta(12)Out[21]: datetime.datetime(2010, 12, 14, 0, 0)
利用str或strftime方法(傳入一個格式化字符串),datetime對象和pandas的Timestamp對象(稍后就會介紹)可以被格式化為字符串:
In [22]: stamp = datetime(2011, 1, 3)In [23]: str(stamp)Out[23]: '2011-01-03 00:00:00'In [24]: stamp.strftime('%Y-%m-%d')Out[24]: '2011-01-03'
datetime.strptime
可以用這些格式化編碼將字符串轉換為日期:
In [26]: datetime.strptime(value, '%Y-%m-%d')Out[26]: datetime.datetime(2011, 1, 3, 0, 0)In [27]: datestrs = ['7/6/2011', '8/6/2011']In [28]: [datetime.strptime(x, '%m/%d/%Y') for x in datestrs]Out[28]: [datetime.datetime(2011, 7, 6, 0, 0), datetime.datetime(2011, 8, 6, 0, 0)]
datetime.strptime
是通過已知格式進行日期解析的最佳方式。但是每次都要編寫格式定義是很麻煩的事情,尤其是對于一些常見的日期格式。
這種情況下,你可以用dateutil這個第三方包中的parser.parse
方法(pandas中已經(jīng)自動安裝好了):
In [29]: from dateutil.parser import parse In [30]: parse('2011-01-03')Out[30]: datetime.datetime(2011, 1, 3, 0, 0)
dateutil可以解析幾乎所有人類能夠理解的日期表示形式:
In [31]: parse('Jan 31, 1997 10:45 PM')Out[31]: datetime.datetime(1997, 1, 31, 22, 45)
在國際通用的格式中,日出現(xiàn)在月的前面很普遍,傳入dayfirst=True
即可解決這個問題:
In [32]: parse('6/12/2011', dayfirst=True)Out[32]: datetime.datetime(2011, 12, 6, 0, 0)
Pandas通常是用于處理成組日期的,不管這些日期是DataFrame的軸索引還是列。to_datetime方法可以解析多種不同的日期表示形式。對標準日期格式(如ISO8601)的解析非常快:
In [33]: datestrs = ['2011-07-06 12:00:00', '2011-08-06 00:00:00']In [34]: pd.to_datetime(datestrs)Out[34]: DatetimeIndex(['2011-07-06 12:00:00', '2011-08-06 00:00:00'], dtype='datetime64[ns]', freq=None)
它還可以處理缺失值(None、空字符串等):
In [35]: idx = pd.to_datetime(datestrs + [None])In [36]: idx Out[36]: DatetimeIndex(['2011-07-06 12:00:00', '2011-08-06 00:00:00', 'NaT'], dty pe='datetime64[ns]', freq=None)In [37]: idx[2]Out[37]: NaT In [38]: pd.isnull(idx)Out[38]: array([False, False, True], dtype=bool)
NaT(Not a Time)
是Pandas中時間戳數(shù)據(jù)的null值。
pandas最基本的時間序列類型就是以時間戳(通常以Python字符串或datatime對象表示)為索引的Series:
In [39]: from datetime import datetime In [40]: dates = [datetime(2011, 1, 2), datetime(2011, 1, 5), ....: datetime(2011, 1, 7), datetime(2011, 1, 8), ....: datetime(2011, 1, 10), datetime(2011, 1, 12)]In [41]: ts = pd.Series(np.random.randn(6), index=dates)In [42]: ts Out[42]: 2011-01-02 -0.2047082011-01-05 0.4789432011-01-07 -0.5194392011-01-08 -0.5557302011-01-10 1.9657812011-01-12 1.393406dtype: float64
這些datetime對象實際上是被放在一個DatetimeIndex中的:
In [43]: ts.index Out[43]: DatetimeIndex(['2011-01-02', '2011-01-05', '2011-01-07', '2011-01-08', '2011-01-10', '2011-01-12'], dtype='datetime64[ns]', freq=None)
跟其他Series一樣,不同索引的時間序列之間的算術運算會自動按日期對齊:
In [44]: ts + ts[::2]Out[44]: 2011-01-02 -0.4094152011-01-05 NaN2011-01-07 -1.0388772011-01-08 NaN2011-01-10 3.9315612011-01-12 NaN dtype: float64
ts[::2] 是每隔兩個取一個。
當你根據(jù)標簽索引選取數(shù)據(jù)時,時間序列和其它的pandas.Series很像:
In [48]: stamp = ts.index[2]In [49]: ts[stamp]Out[49]: -0.51943871505673811
還有一種更為方便的用法:傳入一個可以被解釋為日期的字符串:
In [50]: ts['1/10/2011']Out[50]: 1.9657805725027142In [51]: ts['20110110']Out[51]: 1.9657805725027142
Pandas中的原生時間序列一般被認為是不規(guī)則的,也就是說,它們沒有固定的頻率。對于大部分應用程序而言,這是無所謂的。但是,它常常需要以某種相對固定的頻率進行分析,比如每日、每月、每15分鐘等(這樣自然會在時間序列中引入缺失值)。
幸運的是,pandas有一整套標準時間序列頻率以及用于重采樣、頻率推斷、生成固定頻率日期范圍的工具。
例如,我們可以將之前那個時間序列轉換為一個具有固定頻率(每日)的時間序列,只需調用resample即可:
In [72]: ts Out[72]: 2011-01-02 -0.2047082011-01-05 0.4789432011-01-07 -0.5194392011-01-08 -0.5557302011-01-10 1.9657812011-01-12 1.393406dtype: float64 In [73]: resampler = ts.resample('D')
字符串“D”是每天的意思。
頻率的轉換(或重采樣)是一個比較大的主題。這里,我將告訴你如何使用基本的頻率和它的倍數(shù)。
雖然我之前用的時候沒有明說,但你可能已經(jīng)猜到pandas.date_range可用于根據(jù)指定的頻率生成指定長度的 DatetimeIndex:
In [74]: index = pd.date_range('2012-04-01', '2012-06-01')In [75]: index Out[75]: DatetimeIndex(['2012-04-01', '2012-04-02', '2012-04-03', '2012-04-04', '2012-04-05', '2012-04-06', '2012-04-07', '2012-04-08', '2012-04-09', '2012-04-10', '2012-04-11', '2012-04-12', '2012-04-13', '2012-04-14', '2012-04-15', '2012-04-16', '2012-04-17', '2012-04-18', '2012-04-19', '2012-04-20', '2012-04-21', '2012-04-22', '2012-04-23', '2012-04-24', '2012-04-25', '2012-04-26', '2012-04-27', '2012-04-28', '2012-04-29', '2012-04-30', '2012-05-01', '2012-05-02', '2012-05-03', '2012-05-04', '2012-05-05', '2012-05-06', '2012-05-07', '2012-05-08', '2012-05-09', '2012-05-10', '2012-05-11', '2012-05-12', '2012-05-13', '2012-05-14', '2012-05-15', '2012-05-16', '2012-05-17', '2012-05-18', '2012-05-19', '2012-05-20', '2012-05-21', '2012-05-22', '2012-05-23', '2012-05-24', '2012-05-25', '2012-05-26', '2012-05-27', '2012-05-28', '2012-05-29', '2012-05-30', '2012-05-31', '2012-06-01'], dtype='datetime64[ns]', freq='D')
默認情況下,date_range會產(chǎn)生按天計算的時間點。如果只傳入起始或結束日期,那就還得傳入一個表示一段時間的數(shù)字:
In [76]: pd.date_range(start='2012-04-01', periods=20)Out[76]: DatetimeIndex(['2012-04-01', '2012-04-02', '2012-04-03', '2012-04-04', '2012-04-05', '2012-04-06', '2012-04-07', '2012-04-08', '2012-04-09', '2012-04-10', '2012-04-11', '2012-04-12', '2012-04-13', '2012-04-14', '2012-04-15', '2012-04-16', '2012-04-17', '2012-04-18', '2012-04-19', '2012-04-20'], dtype='datetime64[ns]', freq='D')In [77]: pd.date_range(end='2012-06-01', periods=20)Out[77]: DatetimeIndex(['2012-05-13', '2012-05-14', '2012-05-15', '2012-05-16', '2012-05-17', '2012-05-18', '2012-05-19', '2012-05-20', '2012-05-21', '2012-05-22', '2012-05-23', '2012-05-24', '2012-05-25', '2012-05-26', '2012-05-27','2012-05-28', '2012-05-29', '2012-05-30', '2012-05-31', '2012-06-01'], dtype='datetime64[ns]', freq='D')
起始和結束日期定義了日期索引的嚴格邊界。
例如,如果你想要生成一個由每月最后一個工作日組成的日期索引,可以傳入"BM"頻率(表示business end of month),這樣就只會包含時間間隔內(nèi)(或剛好在邊界上的)符合頻率要求的日期:
In [78]: pd.date_range('2000-01-01', '2000-12-01', freq='BM')Out[78]: DatetimeIndex(['2000-01-31', '2000-02-29', '2000-03-31', '2000-04-28', '2000-05-31', '2000-06-30', '2000-07-31', '2000-08-31', '2000-09-29', '2000-10-31', '2000-11-30'], dtype='datetime64[ns]', freq='BM')
重采樣(resampling)指的是將時間序列從一個頻率轉換到另一個頻率的處理過程。
將高頻率數(shù)據(jù)聚合到低頻率稱為降采樣(downsampling),而將低頻率數(shù)據(jù)轉換到高頻率則稱為升采樣(upsampling)。并不是所有的重采樣都能被劃分到這兩個大類中。
例如,將W-WED(每周三)轉換為W-FRI既不是降采樣也不是升采樣。
Pandas對象都帶有一個resample方法,它是各種頻率轉換工作的主力函數(shù)。resample有一個類似于groupby的API,調用resample可以分組數(shù)據(jù),然后會調用一個聚合函數(shù):
In [208]: rng = pd.date_range('2000-01-01', periods=100, freq='D')In [209]: ts = pd.Series(np.random.randn(len(rng)), index=rng)In [210]: ts Out[210]: 2000-01-01 0.6316342000-01-02 -1.5943132000-01-03 -1.5199372000-01-04 1.1087522000-01-05 1.2558532000-01-06 -0.0243302000-01-07 -2.0479392000-01-08 -0.2726572000-01-09 -1.6926152000-01-10 1.423830 ... 2000-03-31 -0.0078522000-04-01 -1.6388062000-04-02 1.4012272000-04-03 1.7585392000-04-04 0.6289322000-04-05 -0.4237762000-04-06 0.7897402000-04-07 0.9375682000-04-08 -2.2532942000-04-09 -1.772919Freq: D, Length: 100, dtype: float64 In [211]: ts.resample('M').mean()Out[211]: 2000-01-31 -0.1658932000-02-29 0.0786062000-03-31 0.2238112000-04-30 -0.063643Freq: M, dtype: float64 In [212]: ts.resample('M', kind='period').mean()Out[212]: 2000-01 -0.1658932000-02 0.0786062000-03 0.2238112000-04 -0.063643Freq: M, dtype: float64
resample是一個靈活高效的方法,可用于處理非常大的時間序列。
“Python Pandas的知識點有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注億速云網(wǎng)站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。