文章目錄
pandas
文件讀寫
文件讀取
# !/user/bin/python
# -- coding: UTF-8 --
import numpy as np
import pandas as pd
uid=pd.read_csv(r'C:\\Users\\Administrator\\Desktop\\uid_countrycode.csv',header=0)
#讀取txt
uid=pd.read_table(r'C:\\Users\\Administrator\\Desktop\\uid_countrycode.csv',names=['uid','date'])
注:
報錯OSError: Initializing from file failed,一般由兩種情況引起:一種是函數參數爲路徑而非文件名稱,另一種是函數參數帶有中文。
第二種情況,即使路徑、文件名都完整,還是報錯的原因是這個參數中有中文,但是Python3不是已經支持中文了嗎?參考了錯誤原因和pandas的源碼,發現調用pandas的read_csv()方法時,默認使用C engine作爲parser engine,而當文件名中含有中文的時候,用C engine在部分情況下就會出錯。所以在調用read_csv()方法時指定engine爲Python就可以解決問題了。
# !/user/bin/python
uid=pd.read_table(r'C:\\Users\\Administrator\\Desktop\\uid_countrycode.csv',names=['uid','date'],engine='python')
存入文件
#存爲csv文件
other.to_csv(r'C:\\Users\\Administrator\\Desktop\\new.csv',sep=',')
#存爲txt文件
other.to_csv(r'C:\\Users\\Administrator\\Desktop\\new.txt',sep='\t')
預處理
創建dataframe
import pandas as pd
a=[1,2,3]
b=[5,6,7]
c={"a" : a, "b" : b}#將列表a,b轉換成字典
data=pd.DataFrame(c)#將字典轉換成爲數據框
print(data)
簡單處理
查看數據類型
data.dtypes
拼接
uid=[vmoney,paytime,viewtime]
uid=pd.concat(uid)
#注意合併以後重置index
uid = uid.reset_index(drop=True)
匹配合並
df_inner=pd.merge(df,df1,how='inner')
df_left=pd.merge(df,df1,how='left')
df_right=pd.merge(df,df1,how='right')
df_outer=pd.merge(df,df1,how='outer')
命名列名
other.columns=['a','b','c']
替換列值
#前提只r1列存在
data.r1=list(range(len(data.index)))
print data
fecha r1 r2 r3
0 2017-05-01 0 8 6
1 2017-05-02 1 17 4
2 2017-05-03 2 16 11
3 2017-05-04 3 1 2
4 2017-05-05 4 19 9
創建新列
data['r4']=list(range(len(data.index)))
print data
fecha r1 r2 r3 r4
0 2017-05-01 5 14 7 0
1 2017-05-02 4 5 4 1
2 2017-05-03 16 6 11 2
3 2017-05-04 3 8 8 3
#加標籤列/分類列
game.loc[game.onehour>0.5,'new']='A'
game['new']=game['new'].fillna('B')
print game
type num onehour fake_pcu200 day new
0 DOTA II 237 0.49 0.21 2017/7/1 B
1 DOTA II 206 0.52 0.20 2017/7/2 A
2 DOTA II 231 0.52 0.24 2017/7/3 A
3 DOTA II 233 0.53 0.26 2017/7/4 A
4 DOTA II 273 0.56 0.26 2017/7/5 A
5 DOTA II 275 0.54 0.26 2017/7/6 A
6 DOTA II 251 0.53 0.27 2017/7/7 A
分組及排序
#按'type'和'new'列分組,對指定列'onehour'求和
#如果不指定求和列,默認對剩餘所有列求和
game=game.groupby(['type','new'])['onehour'].sum().reset_index()
print game
type new onehour
0 DOTA II A 4.28
1 DOTA II B 1.48
2 Gerena RoV:Mobile MOBA A 4.95
3 Gerena RoV:Mobile MOBA B 1.24
4 Grand Theft Auto V A 4.81
5 Grand Theft Auto V B 1.38
#按指定列排序
game.sort_values(by=['onehour'],ascending=False)
#按索引排序
game.sort_index()
全組排序、組內排序及標號
data['sort_num']=data['comment_num'].rank(ascending=0,method='dense')
第一個參數 ascending,就是選擇是升序還是降序排列。
第二個參數
method=‘dense’
method=‘first’
method=‘min’
method=‘max’
組內排序
data['group_sort']=data['comment_num'].groupby(data['cate']).rank(ascending=0,method='dense')
篩選
簡單操作
篩選出指定行
ID=uid.loc[uid['countrycode']=='ID']
other=uid.loc[uid['countrycode'].isin(['VN','TH','ID'])==False]
篩選掉帶空值的行
other=other.dropna()
對缺失值填充
other=other.fillna()
分組
other=other.groupby('countrycode')
a=[x for x in other]
lambda函數篩選
lambda 參數:表達式
In [85]: df1
Out[85]:
A B C D
a -0.023688 2.410179 1.450520 0.206053
b -0.251905 -2.213588 1.063327 1.266143
c 0.299368 -0.863838 0.408204 -1.048089
d -0.025747 -0.988387 0.094055 1.262731
e 1.289997 0.082423 -0.055758 0.536580
f -0.489682 0.369374 -0.034571 -2.484478
In [86]: df1.loc[lambda df: df.A > 0, :]
Out[86]:
A B C D
c 0.299368 -0.863838 0.408204 -1.048089
e 1.289997 0.082423 -0.055758 0.536580
In [90]: df1.A.loc[lambda s: s > 0]
Out[90]:
c 0.299368
e 1.289997
Name: A, dtype: float64
where篩選
where語句保留了原始series/dataframe的長度和大小,不滿足條件的值默認被替換爲空值NaN
In [166]: df[df < 0]
Out[166]:
A B C D
2000-01-01 -2.104139 -1.309525 NaN NaN
2000-01-02 -0.352480 NaN -1.192319 NaN
2000-01-03 -0.864883 NaN -0.227870 NaN
2000-01-04 NaN -1.222082 NaN -1.233203
#where有other參數,用於替換不滿足條件的值
In [167]: df.where(df < 0, -df)
Out[167]:
A B C D
2000-01-01 -2.104139 -1.309525 -0.485855 -0.245166
2000-01-02 -0.352480 -0.390389 -1.192319 -1.655824
2000-01-03 -0.864883 -0.299674 -0.227870 -0.281059
2000-01-04 -0.846958 -1.222082 -0.600705 -1.233203
#參數還可以爲函數
In [185]: df3 = pd.DataFrame({'A': [1, 2, 3],
.....: 'B': [4, 5, 6],
.....: 'C': [7, 8, 9]})
.....:
In [186]: df3.where(lambda x: x > 4, lambda x: x + 10)
Out[186]:
A B C
0 11 14 7
1 12 5 8
2 13 6 9
DataFrame.where()不同於numpy.where()
df1.where(m, df2)=np.where(m, df1, df2)
In [177]: df.where(df < 0, -df) == np.where(df < 0, df, -df)
Out[177]:
A B C D
2000-01-01 True True True True
2000-01-02 True True True True
2000-01-03 True True True True
#在np裏還可以根據where分組貼標籤
#如果price列的值>3000,group列顯示high,否則顯示low
df_inner['group'] = np.where(df_inner['price'] > 3000,'high','low')
#對複合多個條件的數據進行分組標記
df_inner.loc[(df_inner['city'] == 'beijing') & (df_inner['price'] >= 4000), 'sign']=1
.query()篩選
query括號內允許使用表達式
In [190]: df = pd.DataFrame(np.random.rand(6, 3), columns=list('abc'))
In [191]: df
Out[191]:
a b c
0 0.438921 0.118680 0.863670
1 0.138138 0.577363 0.686602
2 0.595307 0.564592 0.520630
3 0.913052 0.926075 0.616184
4 0.078718 0.854477 0.898725
5 0.076404 0.523211 0.591538
# pure python
In [192]: df[(df.a < df.b) & (df.b < df.c)]
Out[192]:
a b c
1 0.138138 0.577363 0.686602
4 0.078718 0.854477 0.898725
5 0.076404 0.523211 0.591538
# query
In [193]: df.query('(a < b) & (b < c)')
Out[193]:
a b c
1 0.138138 0.577363 0.686602
4 0.078718 0.854477 0.898725
5 0.076404 0.523211 0.591538
# 括號內也可以是比較複雜的表達式
# short query syntax
In [250]: shorter = df.query('a < b < c and (not bools) or bools > 2')
# equivalent in pure Python
In [251]: longer = df[(df.a < df.b) & (df.b < df.c) & (~df.bools) | (df.bools > 2)]
重複值處理
切片
#生成隨機dataframe
import random as rd
import pandas as pd
r1=[rd.randrange(1,20) for x in xrange(62)]
r2=[rd.randrange(1,20) for x in xrange(62)]
r3=[rd.randrange(1,20) for x in xrange(62)]
fecha=pd.date_range('2017-05-01','2017-07-01')
data=pd.DataFrame({'fecha':fecha,'r1':r1,'r2':r2,'r3':r3})
print data
注意此處xrange作用類似range, 但range結果爲list, xrange結果是一個生成器。要生成較大的數字序列時,xrange比range節省內存空間。
[ ]切片方法
In [31]: s[:5]
Out[31]:
2000-01-01 0.469112
2000-01-02 1.212112
2000-01-03 -0.861849
2000-01-04 0.721555
2000-01-05 -0.424972
In [32]: s[::2] #跳行取
Out[32]:
2000-01-01 0.469112
2000-01-03 -0.861849
2000-01-05 -0.424972
In [33]: s[::-1] #逆序取
Out[33]:
2000-01-05 -0.424972
2000-01-04 0.721555
2000-01-03 -0.861849
2000-01-02 1.212112
2000-01-01 0.469112
按照索引實現列切片或區域切片
# 行選擇
data1=data[1:5]
print data1
fecha r1 r2 r3
1 2017-05-02 3 6 15
2 2017-05-03 14 14 11
3 2017-05-04 6 8 12
4 2017-05-05 13 14 2
# 列選擇
data2=data[['r1','r2']]
print data2
r1 r2
0 17 19
1 3 6
2 14 14
3 6 8
4 13 14
5 3 14
6 18 12
7 15 18
8 3 11
9 1 14
10 7 16
11 13 2
12 2 12
13 16 10
14 14 6
15 10 12
16 13 13
17 6 15
18 13 4
19 16 13
20 6 17
21 2 3
22 10 3
23 17 6
24 19 5
25 15 16
26 12 15
27 13 9
28 11 7
29 8 1
30 4 18
31 13 4
# 區塊選擇
data3=data[:10][['r1','r2']]
print data3
r1 r2
0 17 19
1 3 6
2 14 14
3 6 8
4 13 14
5 3 14
6 18 12
7 15 18
8 3 11
9 1 14
.loc
按照標籤進行行列選擇
注意.loc的切片結果包括了第五行,而[ ]不包括。
data1=data.loc[1:5]
print data1
fecha r1 r2 r3
1 2017-05-02 5 16 14
2 2017-05-03 9 5 19
3 2017-05-04 9 7 18
4 2017-05-05 2 4 12
5 2017-05-06 16 18 4
注意下列寫法:
In [15]: df.loc[:,['B', 'A']] = df[['A', 'B']].values
In [16]: df[['A', 'B']]
Out[16]:
A B
2000-01-01 0.469112 -0.282863
2000-01-02 1.212112 -0.173215
2000-01-03 -0.861849 -2.104569
補充
#取特定列
data=data.loc[:,['r1','r3']]
print data
r1 r3
0 8 3
1 2 18
2 18 6
3 1 9
4 13 8
#取連續列報錯
data=data.loc[:,['r1':'r3']]
#取連續列正確方式
data=data.loc[:,'r1':'r3']
print data
r1 r2 r3
0 8 18 15
1 9 13 12
2 10 18 2
3 14 17 2
4 1 2 16
.loc還能選擇特定日期內的數據。但要求日期在索引內。
data_fecha=data.set_index('fecha')
print data_fecha
r1 r2 r3
fecha
2017-05-01 15 4 13
2017-05-02 8 4 11
2017-05-03 6 8 10
2017-05-04 9 19 1
2017-05-05 12 9 7
2017-05-06 18 6 8
2017-05-07 17 14 17
2017-05-08 1 13 16
2017-05-09 13 2 7
2017-05-10 8 16 5
2017-05-11 13 7 16
2017-05-12 6 11 18
2017-05-13 11 7 13
2017-05-14 1 13 12
2017-05-15 19 11 4
2017-05-16 4 8 14
2017-05-17 2 14 15
2017-05-18 6 15 6
2017-05-19 13 9 4
2017-05-20 3 10 7
2017-05-21 11 12 10
2017-05-22 5 17 11
2017-05-23 7 18 17
2017-05-24 3 17 2
2017-05-25 10 8 17
2017-05-26 3 16 9
2017-05-27 9 1 6
2017-05-28 8 8 17
2017-05-29 9 9 16
2017-05-30 4 10 6
2017-05-31 8 18 14
2017-06-01 14 15 14
#生成兩個特定日期
fecha1=dt.datetime(2017,5,5)
fecha2=dt.datetime(2017,5,10)
#生成切片數據
data1=data_fecha.loc[fecha1:fecha2]
print data1
r1 r2 r3
fecha
2017-05-05 18 6 10
2017-05-06 19 12 14
2017-05-07 16 15 8
2017-05-08 8 17 10
2017-05-09 11 14 8
2017-05-10 7 19 16
.iloc
按照索引選取,其括號內只能爲數值。
#行選擇
data1=data[1:5]
print data1
fecha r1 r2 r3
1 2017-05-02 1 6 7
2 2017-05-03 15 9 15
3 2017-05-04 15 10 13
4 2017-05-05 15 15 14
#列選擇
data2=data.iloc[:,[1,3]]
print data2
r1 r3
0 2 18
1 1 7
2 15 15
3 15 13
4 15 14
5 16 7
6 16 9
7 1 5
8 3 9
9 2 1
10 1 17
11 19 3
12 2 2
13 6 14
14 9 10
15 13 6
16 14 14
17 9 8
18 16 13
19 11 14
20 7 10
21 1 12
22 13 1
23 12 19
24 15 17
25 18 8
26 6 17
27 15 3
28 5 12
29 12 1
30 14 19
31 17 13
#切片選擇
data3=data.iloc[[1,5],[1,3]]
print data3
r1 r3
1 1 7
5 16 7
.at
通過標籤訪問單個元素,速度比.loc快
a=data.iat[4,'r1']
print a
12
.iat
類似.iloc,訪問索引提取元素
a=data.iat[4,1]
print a
12
索引
設置索引
#將原有某列設置爲索引
data_fecha=data.set_index('fecha')
r1 r2 r3
fecha
2017-05-01 15 4 13
2017-05-02 8 4 11
2017-05-03 6 8 10
2017-05-04 9 19 1
2017-05-05 12 9 7
#添加新列爲索引
data.index=data['fecha']
fecha r1 r2 r3
fecha
2017-05-01 2017-05-01 6 2 17
2017-05-02 2017-05-02 17 18 5
2017-05-03 2017-05-03 1 9 18
布爾索引
In [140]: df2 = pd.DataFrame({'a' : ['one', 'one', 'two', 'three', 'two', 'one', 'six'],
.....: 'b' : ['x', 'y', 'y', 'x', 'y', 'x', 'x'],
.....: 'c' : np.random.randn(7)})
.....:
# only want 'two' or 'three'
In [141]: criterion = df2['a'].map(lambda x: x.startswith('t'))
In [142]: df2[criterion]
Out[142]:
a b c
2 two y 0.041290
3 three x 0.361719
4 two y -0.238075
# equivalent but slower
In [143]: df2[[x.startswith('t') for x in df2['a']]]
Out[143]:
a b c
2 two y 0.041290
3 three x 0.361719
4 two y -0.238075
# Multiple criteria
In [144]: df2[criterion & (df2['b'] == 'x')]
Out[144]:
a b c
3 three x 0.361719
多重索引
In [152]: s_mi = pd.Series(np.arange(6),index=pd.MultiIndex.from_product([[0, 1], ['a', 'b', 'c']]))
In [153]: s_mi
Out[153]:
0 a 0
b 1
c 2
1 a 3
b 4
c 5
In [154]: s_mi.iloc[s_mi.index.isin([(1, 'a'), (2, 'b'), (0, 'c')])]
Out[154]:
0 c 2
1 a 3
In [155]: s_mi.iloc[s_mi.index.isin(['a', 'c', 'e'], level=1)]
Out[155]:
0 a 0
c 2
1 a 3
c 5
函數
1.apply函數
將函數應用到由各列或行形成的一維數組上。DataFrame的apply方法可以實現此功能
默認情況下會以列爲單位,分別對列應用函數
# 使用apply函數
f=lambda x:x.max()-x.min()
t1=frame.apply(f)
frame['panduan'] = frame.city.apply(lambda x: 1 if 'ing' in x else 0)
frame['test'] = frame.apply(lambda x: function(x.city, x.year), axis = 1)
2.applymap
元素級的python函數,將函數應用到每一個元素
f=lambda x: '%.2f'%x
t3=df.applymap(f)
3.map
Series有一個元素級函數的map方法。而dataframe只有applymap。
# 使用map
result = map(lambda x: 1 if 'ing' in x else 0, frame['panduan'])
# 或
t4=df['e'].map(f)
詳細見官方文檔:http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
4.iterrows()
可以對dataframe循環進行遍歷,返回值爲元組(index,row)
for index,row in otu.iterrows():
print index
print row
numpy
- 在 reshape 函數中使用參數-1
Numpy 允許我們根據給定的新形狀重塑矩陣,新形狀應該和原形狀兼容。有意思的是,我們可以將新形狀中的一個參數賦值爲-1。這僅僅表明它是一個未知的維度,我們希望 Numpy 來算出這個未知的維度應該是多少:Numpy 將通過查看數組的長度和剩餘維度來確保它滿足上述標準。
a.shape
(2, 4)
a.reshape(-1,4)
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
a.reshape(-1,2)
array([[1, 2],
[3, 4],
[5, 6],
[7, 8]])
- Clip:如何使數組中的值保持在一定區間內
在很多數據處理和算法中(比如強化學習中的 PPO),我們需要使得所有的值保持在一個上下限區間內。Numpy 內置的 Clip 函數可以解決這個問題。Numpy clip () 函數用於對數組中的值進行限制。給定一個區間範圍,區間範圍外的值將被截斷到區間的邊界上。例如,如果指定的區間是 [-1,1],小於-1 的值將變爲-1,而大於 1 的值將變爲 1。
#Example-1
array = np.array([10, 7, 4, 3, 2, 2, 5, 9, 0, 4, 6, 0])
print (np.clip(array,2,6))
[6 6 4 3 2 2 5 6 2 4 6 2]
- Extract:從數組中提取符合條件的元素
arr = np.arange(10)
arrarray([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) # Define the codition, here we take MOD 3 if zero
condition = np.mod(arr, 3)==0
conditionarray([ True, False, False, True, False, False, True, False, False,True])
np.extract(condition, arr)
array([0, 3, 6, 9])
- setdiff1d:如何找到僅在 A 數組中有而 B 數組沒有的元素
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
b = np.array([3,4,7,6,7,8,11,12,14])
c = np.setdiff1d(a,b)
c
array([1, 2, 5, 9])