pandas

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

  1. 在 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]])
  1. 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]
  1. 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])
  1. 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])
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章