Pandas学习笔记

pandas是建立在Numpy基础上的高效数据分析处理库,pandas提供了众多的高级函数,可以极大地简化了数据分析处理的流程。

以下为自己学习pandas的部分笔记,如有错误,欢迎指出

import numpy as np
import pandas as pd

Pandas的数据结构

pandas有三种数据结构(很快就只用两种了),分别为Series(序列),DataFrame(数据框),Panel(面板),其中panel将在0.24版本被弃用,故就不介绍了。

1、Series(序列):可以看成是具有索引的一维数组

使用pd.Series(x,index=idx):x可以为列表,一维数组,字典

第一种生成序列的方法:直接给定一个一维数组或者列表

series01 = pd.Series(np.arange(1,5))##series01 = pd.Series([1,2,3,4])
series01
0    1
1    2
2    3
3    4
dtype: int32

第二种方法:使用字典来生成序列;其中字典的keys值会直接变为序列的索引,values变为序列的数据值。

d = {'No.1':'Hajo','No.2':'Mike','No.3':'John','No.4':'Shanel'}
series02 = pd.Series(d)
series02
No.1      Hajo
No.2      Mike
No.3      John
No.4    Shanel
dtype: object

通过index和values属性可以查看序列的索引值和数据值

print('series的索引值为:\n',series01.index)
print('series的数据值为:\n',series01.values)
series的索引值为:
 RangeIndex(start=0, stop=4, step=1)
series的数据值为:
 [1 2 3 4]

创建序列时可以对序列的索引进行声明,亦可以在创建后在进行声明

#创建时声明索引
series03 = pd.Series(np.arange(1,6),index=['Hajo','Mike','John','Joe','Shanel'])
series03
Hajo      1
Mike      2
John      3
Joe       4
Shanel    5
dtype: int32
#创建后声明(对series01的索引声明为A,B,C,D)
print('原序列:\n',series01)
series01.index=['A','B','C','D'] ##声明的索引必须与序列的数据值的长度相等
print('改变后的序列series01:\n',series01)
原序列:
 0    1
1    2
2    3
3    4
dtype: int32
改变后的序列series01:
 A    1
B    2
C    3
D    4
dtype: int32

序列有一个name属性,可以通过该属性定义序列的名字

##对series02进行命名为:排名
series02.name='排名'
print('series02_name:\n',series02.name)
#创建时命名
##d = {'No.1':'Hajo','No.2':'Mike','No.3':'John','No.4':'Shanel'}
#series02 = pd.Series(d,name='排名')
series02_name:
 排名

二、DataFrame(数据框):二维数据;每一行代表一个示例(instance),每一列代表一个特征(feature);可以理解为DateFrame是Series的容器。

使用pd.DataFrame(x,index=idx,columns=col),x:二维列表,二维数组,字典(其值是一维列表,numpy数组或者Series),另一个DataFrame;index:行索引;columns:列索引

第一种方法:使用numpy数组或二维列表

#df01 = pd.DataFrame([[1,2,3,4],[6,7,8,9]])
df01 = pd.DataFrame(np.array([[1,2,3,4],[6,7,8,9]]))
df01
0123
01234
16789

第二种方法:使用字典(对象为一维列表);字典的keys值变为columns索引,values变为columns的值

indexs = ['Hajo','Mike','John','Joe','Shanel']
date = {'gender':['male','male','male','female','female'],
       'score':[89,87,95,93,99]}
df2 = pd.DataFrame(date,index=indexs)
df2.index.name='name'
df2.columns.name='分割'
df2
分割genderscore
name
Hajomale89
Mikemale87
Johnmale95
Joefemale93
Shanelfemale99
##将index中的名字改变为A,B,C,D,E
df2.index=['A','B','C','D','E'] ##只能整体改变,不可以只改变一个
df2
分割genderscore
Amale89
Bmale87
Cmale95
Dfemale93
Efemale99

DataFrame的部分属性:df.shape,df.index,df.values,df.columns

print('df2的部分属性:\n')
print('df2的形状:\n',df2.shape)
print('df2的index:\n',df2.index)
print('df2的values:\n',df2.values)
print('df2的columns:\n',df2.columns)
df2的部分属性:

df2的形状:
 (5, 2)
df2的index:
 Index(['A', 'B', 'C', 'D', 'E'], dtype='object')
df2的values:
 [['male' 89]
 ['male' 87]
 ['male' 95]
 ['female' 93]
 ['female' 99]]
df2的columns:
 Index(['gender', 'score'], dtype='object', name='分割')

查看DataFrame:通过df.head(n),df.tail(n)可以从头部或尾部查看DataFrame的n行,n默认为5

df2.head(3)
分割genderscore
Amale89
Bmale87
Cmale95
df2.tail(3)
分割genderscore
Cmale95
Dfemale93
Efemale99

统计DataFrame:使用df.describe()

df2.describe()
分割score
count5.000000
mean92.600000
std4.774935
min87.000000
25%89.000000
50%93.000000
75%95.000000
max99.000000

数据框的索引和切片

Series的索引和切片与numpy数组的类似,所以主要学习DataFrame的索引和切片

DataFrame的索引和切片可以基于标签,也可以基于位置,不像numpy数组只能基于位置;所以DataFrame的索引和切片有四大类:a、索引单元素;b、切片columns;c、切片index;d、切片columns和index

a、索引单元素:基于标签的at;基于位置的iat;

b、切片columns:用 . 来切片单列;用[]来切片单列或多列;基于标签的loc;基于位置的iloc;

c、切片index:用[]来切片单列或多列;基于标签的loc;基于位置的iloc;

d、切片columns和index:基于标签的loc,基于位置的iloc

总的来说,主要有两种使用:基于标签的at、loc;基于位置的iat、iloc;其实在最后使用时,一般我们使用的都会是loc或者iloc

symbol = ['BABA','JD','APPL','MS','GS','WMT']
data1 = {'行业':['电商','电商','科技','金融','金融','零售'],
        '价格':[176.92,25.95,172.97,41.79,196.00,99.55],
        '交易量':[16175612,27113297,19856335,10151252,12553515,8086946],
        '雇员':[101550,175336,100000,60348,36600,220000]}
df02 = pd.DataFrame(data1,index=symbol)
df02.name='美股'
df02.index.name='代号'
df02
行业价格交易量雇员
代号
BABA电商176.9216175612101550
JD电商25.9527113297175336
APPL科技172.9719856335100000
MS金融41.791015125260348
GS金融196.001255351536600
WMT零售99.558086946220000

a、索引单元素—只举例at和iat

##获取苹果公司的价格
APPL_Price1 = df02.at['APPL','价格']
APPL_Price2 = df02.iat[2,1]
print('基于标签:',APPL_Price1)
print('基于位置:',APPL_Price2)
基于标签: 172.97
基于位置: 172.97

b、切片columns–只举例loc和iloc

##获取价格这一列
col_Price = df02.loc[:,'价格']
col_Price1 = df02.iloc[:,1]
print('基于标签:\n',col_Price)
print('介于位置:\n',col_Price1)
基于标签:
 代号
BABA    176.92
JD       25.95
APPL    172.97
MS       41.79
GS      196.00
WMT      99.55
Name: 价格, dtype: float64
介于位置:
 代号
BABA    176.92
JD       25.95
APPL    172.97
MS       41.79
GS      196.00
WMT      99.55
Name: 价格, dtype: float64

c、切片index

##获取京东的整个信息
JD_info = df02.loc['JD',:]
JD_info1 = df02.iloc[1,:]
print('基于标签:\n',JD_info)
print('基于位置:\n',JD_info1)
基于标签:
 行业           电商
价格        25.95
交易量    27113297
雇员       175336
Name: JD, dtype: object
基于位置:
 行业           电商
价格        25.95
交易量    27113297
雇员       175336
Name: JD, dtype: object

d、切片index和columns:这一种其实就是上面两种的结合,不同的是上面两种要么获取整行,要么获取整列,所以可以这样认为上面两种就是第四种方法的特类

##获取BABA,JD,APPL的价格和交易量
info = df02.loc[['BABA','JD','APPL'],['价格','交易量']]
info1 = df02.iloc[0:3,1:3]
print('基于标签:\n',info)
print('基于位置:\n',info1)
基于标签:
           价格       交易量
代号                    
BABA  176.92  16175612
JD     25.95  27113297
APPL  172.97  19856335
基于位置:
           价格       交易量
代号                    
BABA  176.92  16175612
JD     25.95  27113297
APPL  172.97  19856335
高级索引:布尔索引
##筛选雇员大于100000的公司
print(df02.雇员>=100000)
df02.loc[df02.雇员 >= 100000,:]
代号
BABA     True
JD       True
APPL     True
MS      False
GS      False
WMT      True
Name: 雇员, dtype: bool
行业价格交易量雇员
代号
BABA电商176.9216175612101550
JD电商25.9527113297175336
APPL科技172.9719856335100000
WMT零售99.558086946220000

多个筛选条件可以使用逻辑运算符:&,|;需要注意运算的优先级–使用括号()

##筛选价格大于150,雇员小于100000的公司
df02.loc[(df02.价格>150)&(df02.雇员<100000),:]
行业价格交易量雇员
代号
GS金融196.01255351536600

数据表的合并与连接

数据表可以按‘键’合并,用merge函数;也可以按‘轴’连接,使用concat函数。

按键合并

merge函数,用法:pd.merge(df1,df2,how=‘inner’,on=c,suffixes=[]);
参数how:是使用合并方式,四种:
inner(默认)–>合并所有行即将两个数据表的行索引全部显示相当于并集,
outer–>合并df1和df2共有的行即相当于交集,
left–>连接后显示左边df1的所有行即保留df2中df1有的行,去除df2中df1没有的;
right–>连接后保留右边df2中所有的行即保留df1中df2有的,去除df1中df2没有的。
参数on:df1和df2共有的一栏或者多栏,所以跟c的栏数即列名columns_name,又分为单键合并和多键合并。
参数suffixes:设置后缀名,
后缀名的产生:当合并时,两个df除了合并的键,还有其他具有相同名称(列名)的键时,就会产生,默认是加上’_x,_y’

##创建两个DataFrame
d_left = {'Date':pd.date_range('2019-1-1',periods=4),
          'temperate':[17.3,18.6,17.2,18]}
df_left = pd.DataFrame(d_left)
df_left
Datetemperate
02019-01-0117.3
12019-01-0218.6
22019-01-0317.2
32019-01-0418.0
d_right = {'Date':pd.date_range('2019-1-3',periods=4),
           'weather':['good','good','bad','good']}
df_right = pd.DataFrame(d_right)
df_right
Dateweather
02019-01-03good
12019-01-04good
22019-01-05bad
32019-01-06good
##根据Date中的值来合并
##默认内链接inner
inner_df = pd.merge(df_left,df_right,how='inner',on=['Date'])
print('内连接:\n',inner_df)
##外连接outer
outer_df = pd.merge(df_left,df_right,how='outer',on=['Date'])
print('外连接:\n',outer_df)
##左连接left join
left_df = pd.merge(df_left,df_right,how='left')
print('左连接:\n',left_df)
##右连接 right join
right_df = pd.merge(df_left,df_right,how='right')
print('右连接:\n',right_df)
内连接:
         Date  temperate weather
0 2019-01-03       17.2    good
1 2019-01-04       18.0    good
外连接:
         Date  temperate weather
0 2019-01-01       17.3     NaN
1 2019-01-02       18.6     NaN
2 2019-01-03       17.2    good
3 2019-01-04       18.0    good
4 2019-01-05        NaN     bad
5 2019-01-06        NaN    good
左连接:
         Date  temperate weather
0 2019-01-01       17.3     NaN
1 2019-01-02       18.6     NaN
2 2019-01-03       17.2    good
3 2019-01-04       18.0    good
右连接:
         Date  temperate weather
0 2019-01-03       17.2    good
1 2019-01-04       18.0    good
2 2019-01-05        NaN     bad
3 2019-01-06        NaN    good

以上的是单键合并,下面举个多键合并的例子:

##创建两个df
df_left1 = pd.DataFrame({'Date':pd.date_range('2019-1-1',periods=4),
                        'temperate':[20,21,22,23],
                        'weather':['good','bad','bad','bad']})
df_left1
Datetemperateweather
02019-01-0120good
12019-01-0221bad
22019-01-0322bad
32019-01-0423bad
df_right1 = pd.DataFrame({'Date':pd.date_range('2019-1-3',periods=4),
                         'temperate':[18,17,16,15],
                         'weather':['bad','good','good','bad']})
df_right1
Datetemperateweather
02019-01-0318bad
12019-01-0417good
22019-01-0516good
32019-01-0615bad

在Date和temperate两个键上做外合并

##多键外合并
l_df = pd.merge(df_left1,df_right1,how='outer',on=['Date','temperate'])
l_df
Datetemperateweather_xweather_y
02019-01-0120goodNaN
12019-01-0221badNaN
22019-01-0322badNaN
32019-01-0423badNaN
42019-01-0318NaNbad
52019-01-0417NaNgood
62019-01-0516NaNgood
72019-01-0615NaNbad
##添加后缀名
l_df = pd.merge(df_left1,df_right1,how='outer',on=['Date','temperate'],suffixes=['_left','_right'])
l_df
Datetemperateweather_leftweather_right
02019-01-0120goodNaN
12019-01-0221badNaN
22019-01-0322badNaN
32019-01-0423badNaN
42019-01-0318NaNbad
52019-01-0417NaNgood
62019-01-0516NaNgood
72019-01-0615NaNbad
按轴连接

Series和DataFrame相互连接,使用pd.concat函数

用法:pd.concat([s1,s2,s3…],axis=0)或者pd.concat([df1,df2,df3,…],axis=0)

Series连接时:axis=0,会得到更长的Series;axis=1,则会变成一个DataFrame.

###使用pd.concat()连接三个Series
s1 = pd.Series([0,1],index=['a','b'])
s2 = pd.Series([2,3],index=['c','d'])
s3 = pd.Series([4,5],index=['e','f'])
pd.concat([s1,s2,s3],axis=0)
a    0
b    1
c    2
d    3
e    4
f    5
dtype: int64
pd.concat([s1,s2,s3],axis=1,sort='True')
012
a0.0NaNNaN
b1.0NaNNaN
cNaN2.0NaN
dNaN3.0NaN
eNaNNaN4.0
fNaNNaN5.0
##使用pd.concat()连接两个DateFrame
df1 = pd.DataFrame({'name':['Hajo','Mike'],
                    'gender':['female','female'],
                   'age':[21,22]})
df2 = pd.DataFrame({'name':['Joe','Shanel'],
                   'gender':['male','male'],
                   'age':[20,21]})
pd.concat([df1,df2],axis=0)
namegenderage
0Hajofemale21
1Mikefemale22
0Joemale20
1Shanelmale21
pd.concat([df1,df2],axis=1)
namegenderagenamegenderage
0Hajofemale21Joemale20
1Mikefemale22Shanelmale21

数据表的重塑和透视

重塑(reshape)和透视(pivot)两个操作只改变数据表的布局(layout):
·重塑用stack和unstack函数(互为逆转操作)
·透视用pivot和melt函数(互为逆转操作)

重塑

重塑:简单点理解就是行索引与列索引的相互转换,从而来改变数据表的展示形式。
·列索引➡行索引,用stack函数
·行索引➡列索引,用unstack函数

name_symbol = ['Hajo','Shanel']
info_data = {'行业':['IT','金融'],
             '年龄':[23,22],
            '工资':[15000,9000]}
person_df = pd.DataFrame(info_data,index=name_symbol)
person_df.columns.name = '信息类别'
person_df.index.name = '姓名'
person_df
信息类别行业年龄工资
姓名
HajoIT2315000
Shanel金融229000

stack:列索引➡行索引
原来的DataFrame person_df 变成两层Series(第一层索引为姓名,第二层索引为信息类别)

c2i_Series = person_df.stack()
c2i_Series
姓名      信息类别
Hajo    行业         IT
        年龄         23
        工资      15000
Shanel  行业         金融
        年龄         22
        工资       9000
dtype: object

unstack:行索引➡列索引
原来的DateFrame person_df 也变成两层Series(第一层索引为信息类别,第二层索引为姓名)

i2c_Series = person_df.unstack()
i2c_Series
信息类别  姓名    
行业    Hajo         IT
      Shanel       金融
年龄    Hajo         23
      Shanel       22
工资    Hajo      15000
      Shanel     9000
dtype: object

从上面可以发现:stack其实是将DataFrame,重新按index进行分类显示
unstack则是将DataFrame,重新按columns进行分类显示。
这只是对于单层DataFrame来说,也是我的理解,其实对于多层DataFrame也差不多,只不过要考虑到想按那一层索引来分类而已。

透视

Pandas里透视的方法有两种:
·用pivot函数将‘一张长表’变‘多张宽表’;
·用melt函数将‘多张宽表’变‘一张长表’本次使用数据是5只股票(AAPL,JD,BABA,FB,GS)4个交易日(2019-02-21 to 2019-02-26)的交易信息(数据来源:微信公众号:【王的机器】,顺便说下,这个公众号挺好的,有很多关于量化交易,数据分析和机器学习等方面的文章,需要的可以关注哦),文末有链接下载!!!

data = pd.read_csv('Stock.csv',parse_dates=[0],dayfirst=True)
##结果为20行,这里只显示前5行和后5行
data.head().append(data.tail())
DateSymbolOpenHighLowCloseAdj CloseVolume
02019-02-21AAPL171.800003172.369995170.300003171.059998171.05999817249700
12019-02-21JD24.82000024.87999924.01000024.27000024.27000013542600
22019-02-21BABA171.000000171.779999169.800003171.660004171.6600048434800
32019-02-21GS198.970001199.449997195.050003196.360001196.3600012785900
42019-02-21FB161.929993162.240005159.589996160.039993160.03999315607800
152019-02-26AAPL173.710007175.300003173.169998174.330002174.33000217006000
162019-02-26JD25.98000026.82000025.66000026.59000026.59000020264100
172019-02-26BABA179.789993184.350006179.369995183.539993183.53999313857900
182019-02-26GS198.470001200.559998196.550003198.899994198.8999942498000
192019-02-26FB164.339996166.240005163.800003164.130005164.13000513645200

从长到宽:df.pivot()
pivot函数会将原始的数据表透视成一个新的数据表,故主要的语法可以这样理解:
df.pivot(index=[],columns=’’,values=[])
index:新数据表的行索引,可以不设置,默认是数字索引,也可从把原始数据表中一个columns当成index;
columns:新数据表的列索引,与index的设置一样,从原始数据表中指定一个。
values:新数据表的值,从原始数据表中指定需要查看的一个或多个标签(一般是columns),如果不指定,则会显示除了被设置为index和columns的所有原始数据表的columns

"""
将index设置为date,
将columns设置为symbol,
将values指定为Adj Close
"""
close_df = data.pivot(index = 'Date',
                     columns = 'Symbol',
                     values = 'Adj Close')
close_df
SymbolAAPLBABAFBGSJD
Date
2019-02-21171.059998171.660004160.039993196.36000124.270000
2019-02-22172.970001176.919998161.889999196.00000025.950001
2019-02-25174.229996183.250000164.619995198.64999426.190001
2019-02-26174.330002183.539993164.130005198.89999426.590000
##将values指定为Adj Close,Open,Volume,来查看多个内容
data.pivot(index = 'Date',
          columns = 'Symbol',
          values = ['Adj Close','Open','Volume'])
Adj CloseOpenVolume
SymbolAAPLBABAFBGSJDAAPLBABAFBGSJDAAPLBABAFBGSJD
Date
2019-02-21171.059998171.660004160.039993196.36000124.270000171.800003171.000000161.929993198.97000124.82000017249700.08434800.015607800.02785900.013542600.0
2019-02-22172.970001176.919998161.889999196.00000025.950001171.580002172.800003160.580002196.60000624.54999918913200.016175600.015858500.02626600.027113300.0
2019-02-25174.229996183.250000164.619995198.64999426.190001174.160004181.259995163.070007198.00000027.11000121873400.022831800.018737100.03032200.029338500.0
2019-02-26174.330002183.539993164.130005198.89999426.590000173.710007179.789993164.339996198.47000125.98000017006000.013857900.013645200.02498000.020264100.0
##不设置values
all_pivot = data.pivot(index = "Date",
                      columns = "Symbol")
all_pivot
OpenHigh...Adj CloseVolume
SymbolAAPLBABAFBGSJDAAPLBABAFBGSJD...AAPLBABAFBGSJDAAPLBABAFBGSJD
Date
2019-02-21171.800003171.000000161.929993198.97000124.820000172.369995171.779999162.240005199.44999724.879999...171.059998171.660004160.039993196.36000124.27000017249700843480015607800278590013542600
2019-02-22171.580002172.800003160.580002196.60000624.549999173.000000177.020004162.410004197.75000025.959999...172.970001176.919998161.889999196.00000025.950001189132001617560015858500262660027113300
2019-02-25174.160004181.259995163.070007198.00000027.110001175.869995183.720001166.070007201.50000027.379999...174.229996183.250000164.619995198.64999426.190001218734002283180018737100303220029338500
2019-02-26173.710007179.789993164.339996198.47000125.980000175.300003184.350006166.240005200.55999826.820000...174.330002183.539993164.130005198.89999426.590000170060001385790013645200249800020264100

4 rows × 30 columns

从宽到长: pd.melt()
pd.melt(DataFrame,id_vars=[],value_vars=[],var_name=’’,value_name=’’)
·id_vars:id–>可以这样理解为id不是分类索引
·value_vars:variable–>理解为是分类索引
·var_name:分类索引的列名,默认是variable
·value_name:对应于原始数据表中分类索引的对应值的列名
***** var_name和value_name参数说的很拗口,看第二个例子就会理解了

具体来说,函数 melt 实际是将「源表」转化成 id-variable 类型的 DataFrame,下例将
·Date 和 Symbol 列当成 id
·其他列 Open, High, Low, Close, Adj Close 和 Volume 当成 variable,而它们对应的值当成 value

melted_data = pd.melt(data,id_vars=['Date','Symbol'])
##显示前5行和后5行
melted_data.head(5).append(melted_data.tail(5))
DateSymbolvariablevalue
02019-02-21AAPLOpen1.718000e+02
12019-02-21JDOpen2.482000e+01
22019-02-21BABAOpen1.710000e+02
32019-02-21GSOpen1.989700e+02
42019-02-21FBOpen1.619300e+02
1152019-02-26AAPLVolume1.700600e+07
1162019-02-26JDVolume2.026410e+07
1172019-02-26BABAVolume1.385790e+07
1182019-02-26GSVolume2.498000e+06
1192019-02-26FBVolume1.364520e+07
##设置var_name和value_name
pd.melt(data,id_vars=['Date','Symbol'],var_name='分类类别',value_name='对应值').head()
DateSymbol分类类别对应值
02019-02-21AAPLOpen171.800003
12019-02-21JDOpen24.820000
22019-02-21BABAOpen171.000000
32019-02-21GSOpen198.970001
42019-02-21FBOpen161.929993

对于透视:其实可以理解为将需要查看的属性分类出来,便于我们的理解。

数据表的分组和整合

DataFrame 中的数据可以根据某些规则分组,然后在每组的数据上计算出不同统计量。这种操作称之为 split-apply-combine,简单理解就是:我们先将数据表按各种标签分组,再通过运算操作,将各个标签的内容进行分析,最后再整合成需要的数据表。由于不需要太多数据,需要处理一下数据,保留数据中的’Date’,Symbol’和’Adj Close’

##读取数据并进行数据处理:
data = pd.read_csv('1Y_Stock_Data.csv',parse_dates=[0],dayfirst=True)
data = data[['Date','Symbol','Adj Close']]
data.insert(1,'Year',pd.DatetimeIndex(data['Date']).year)
data.insert(2,'Month',pd.DatetimeIndex(data['Date']).month)
data.head(3).append(data.tail(3))
DateYearMonthSymbolAdj Close
02018-02-2620182AAPL176.285675
12018-02-2720182AAPL175.714386
22018-02-2820182AAPL175.448410
12572019-02-2220192GS196.000000
12582019-02-2520192GS198.649994
12592019-02-2620192GS198.899994
分组(grouping)

用一组特定标签(label)将数据(data)进行分组:
data.groupby(label)
返回的是一个DataFrameGroupBy类型,有以下部分属性和方法:
·ngroups:组的个数(int)
·size():每组元素的个数(Series)
·groups:每组元素在原DataFrame中的索引信息(dict)
·get_groups(label):标签label对应的数据(DataFrame)

##定义一个print_groups函数来打印组的名字和前5行信息:
def print_groups(group_ojb):
    for name,group in group_ojb:
        print(name)
        print(group.head())
##单标签分组
grouped = data.groupby('Symbol')
print_groups(grouped)
AAPL
        Date  Year  Month Symbol   Adj Close
0 2018-02-26  2018      2   AAPL  176.285675
1 2018-02-27  2018      2   AAPL  175.714386
2 2018-02-28  2018      2   AAPL  175.448410
3 2018-03-01  2018      3   AAPL  172.375214
4 2018-03-02  2018      3   AAPL  173.567078
BABA
          Date  Year  Month Symbol   Adj Close
252 2018-02-26  2018      2   BABA  194.190002
253 2018-02-27  2018      2   BABA  188.259995
254 2018-02-28  2018      2   BABA  186.139999
255 2018-03-01  2018      3   BABA  181.990005
256 2018-03-02  2018      3   BABA  179.759995
FB
          Date  Year  Month Symbol   Adj Close
756 2018-02-26  2018      2     FB  184.929993
757 2018-02-27  2018      2     FB  181.460007
758 2018-02-28  2018      2     FB  178.320007
759 2018-03-01  2018      3     FB  175.940002
760 2018-03-02  2018      3     FB  176.619995
GS
           Date  Year  Month Symbol   Adj Close
1008 2018-02-26  2018      2     GS  267.574249
1009 2018-02-27  2018      2     GS  264.289459
1010 2018-02-28  2018      2     GS  260.085419
1011 2018-03-01  2018      3     GS  254.001984
1012 2018-03-02  2018      3     GS  255.327515
JD
          Date  Year  Month Symbol  Adj Close
504 2018-02-26  2018      2     JD  48.799999
505 2018-02-27  2018      2     JD  47.040001
506 2018-02-28  2018      2     JD  47.150002
507 2018-03-01  2018      3     JD  46.209999
508 2018-03-02  2018      3     JD  43.799999
##多标签分组
grouped2 = data.groupby(['Symbol','Year','Month'])
#print_groups(grouped2)
整合(aggregating)
##用mean()函数计算每个Symbol下一年的股价均值
grouped.mean()
YearMonthAdj Close
Symbol
AAPL2018.1507946.488095186.022309
BABA2018.1507946.488095171.780992
FB2018.1507946.488095167.244841
GS2018.1507946.488095221.593412
JD2018.1507946.48809531.340754
##使用内置函数agg()作用到组对象上
result = grouped.agg(lambda x :np.max(x)-np.min(x))
result.head().append(result.tail())
DateYearMonthAdj Close
Symbol
AAPL365 days11188.692703
BABA365 days11180.259995
FB365 days11193.440002
GS365 days111114.072418
JD365 days11129.529999
AAPL365 days11188.692703
BABA365 days11180.259995
FB365 days11193.440002
GS365 days111114.072418
JD365 days11129.529999

Pandas文件读取与存储

跟numpy库一样。pandas库也提供了文件的读取和存储,而我们一般也是使用pandas的这一部分来对文件进行读取的 pandas支持对多种文件的读取和存储如:csv文件,json文件,excel文件,hdf文件(一种二进制文件格式),这里主要讲csv文件的操作,也是我们最常用的文件操作。读取语法:
pd.read_csv(path,usecols=[],names=[],index_col=[],encoding=’’)

  • path:文件路径
  • usecols:针对有表头文件,需要的字段
  • names:针对无表头文件,需要的表头字段
  • index_col:将某列设置为index
  • encoding:编码格式
    存储语法:
    df.to_csv(path,columns,mode=‘w’,index=False,header=False,encoding=’’)
  • path:文件存储路径
  • columns:列名
  • mode:存储模式,‘w’–>重写;‘a’–>追加
  • index;是否加入行索引,默认False
  • header:是否添加表头,默认False
  • encoding:编码格式(这里说下,如果你使用’utf_8’后中文依旧是乱码,请改为’utf_8_sig’)
##对person_df进行操作
person_df
信息类别行业年龄工资
姓名
HajoIT2315000
Shanel金融229000
##存储到当前目录下,并命名为info.csv
person_df.to_csv('info.csv',encoding='utf_8_sig')
##读取出info.csv
person_df2 = pd.read_csv('info.csv',index_col=['姓名'])
person_df2
行业年龄工资
姓名
HajoIT2315000
Shanel金融229000

#################################################################################

以上就是pandas的一些基本操作,主要用于对数据的分析为主。
下面的是利用pandas对数据进行预处理的一些操作笔记。(可能例子会少一些)

DataFrame运算

1、算术运算:
- 使用运算符;
- 使用运算方法如df.add(other_df),df.sub(other_df)
2、逻辑运算:
- 运算符:<,>,|,&,<=,>=
- bool索引:类似于data[data[‘high’]>15]
- 组合逻辑:(需要注意优先级)
例如:data[(data[‘high’]>15)&(data[‘low’]<15)]
使用query()方法:data.query(‘high>15&low<15’) 与上式相同结果
使用isin()方法:判断data中turnover是否含有4.19,4.39–>data[data[‘turnover’].isin(4.19,4.39)]
3、统计运算:
- 使用max,min,mean,median,var,std依次返回常见的指标:最大值,最小值,均值,中位数,方差,标准差
- data.describe()–>直接返回上面的指标
4、自定义运算;
- 使用apply()函数,其语法:
apply(func,axis=0)
func:自定义函数
axis:作用的方向,默认是列即axis=0,axis=1–>行

data = pd.read_csv('Stock.csv')
data.head()
DateSymbolOpenHighLowCloseAdj CloseVolume
021/02/2019AAPL171.800003172.369995170.300003171.059998171.05999817249700
121/02/2019JD24.82000024.87999924.01000024.27000024.27000013542600
221/02/2019BABA171.000000171.779999169.800003171.660004171.6600048434800
321/02/2019GS198.970001199.449997195.050003196.360001196.3600012785900
421/02/2019FB161.929993162.240005159.589996160.039993160.03999315607800
##提取data中的Open列,并全部加上10
data_open = data['Open']
data_open = data_open + 10
##data_open = data_open.add(10)
data_open.head()
0    181.800003
1     34.820000
2    181.000000
3    208.970001
4    171.929993
Name: Open, dtype: float64
##筛选出Symbol为DJ,且High小于25的所有内容
data[(data['Symbol']=='JD')&(data['High']<25)]
DateSymbolOpenHighLowCloseAdj CloseVolume
121/02/2019JD24.8224.87999924.0124.2724.2713542600
##查看dat所有常见指标
data.describe()
OpenHighLowCloseAdj CloseVolume
count20.00000020.00000020.00000020.00000020.0000002.000000e+01
mean147.026001148.733501146.126000147.577499147.5774991.506961e+07
std63.44484464.00565163.20879363.61536863.6153687.879190e+06
min24.54999924.87999924.01000024.27000024.2700002.498000e+06
25%161.592495162.367504160.129998161.427497161.4274971.226565e+07
50%171.690002172.684998170.840004172.315002172.3150021.601705e+07
75%180.157493183.877502179.709995183.322498183.3224981.925092e+07
max198.970001201.500000197.710007198.899994198.8999942.933850e+07
##使用apply()函数提取出所有列中的最大值
data_cols = data.iloc[:,2:]
data_cols.apply(lambda x : np.max(x))
Open         1.989700e+02
High         2.015000e+02
Low          1.977100e+02
Close        1.989000e+02
Adj Close    1.989000e+02
Volume       2.933850e+07
dtype: float64

缺失值处理

有时候我们得到文件可能会存在部分的缺失值,这时就得对这些缺失值进行处理,从而减少由于缺失值而带来的误差:
常见的思路有两种:
a、样本数据足够多时,可以选择直接删除缺失值
b、样本数据不足时,使用插补法进行处理(使用该列的均值,中位数等)NaN类型处理流程:
1,判断数据中是否有缺失值(NaN):
pd.isnull(df)–>是NaN,标记为True;
pd.notnull(df)–>是NaN,标记为False;
2,处理缺失值:
a、直接删除:
df.dropna(axis=1),默认按行删除即axis=1
b、替换/插补:
df.fillna(value,inplace=False)–>value:填补的值
inplace:是否就地填补即在原数据中进行填补,默认False非NaN类型的处理流程则需先将该标记(?,空格,等特殊符号)转换为NaN类型,在进行上述的处理。
处理函数:
df.replace(to_replace=’’,value=),to_replace:被替换内容,value:替换值,一般为np.nan

##提取data中Date为2019-02-21这天5只股票股市情况,并将部分值设为?
data_Date = data[data['Date']=='21/02/2019']
data_Date.iloc[1,3]='?'
data_Date.iloc[1,4]='?'
data_Date
DateSymbolOpenHighLowCloseAdj CloseVolume
021/02/2019AAPL171.800003172.37170.3171.059998171.05999817249700
121/02/2019JD24.820000??24.27000024.27000013542600
221/02/2019BABA171.000000171.78169.8171.660004171.6600048434800
321/02/2019GS198.970001199.45195.05196.360001196.3600012785900
421/02/2019FB161.929993162.24159.59160.039993160.03999315607800
##先转换为NaN类型
data_Date = data_Date.replace(to_replace='?',value=np.nan)
data_Date
DateSymbolOpenHighLowCloseAdj CloseVolume
021/02/2019AAPL171.800003172.369995170.300003171.059998171.05999817249700
121/02/2019JD24.820000NaNNaN24.27000024.27000013542600
221/02/2019BABA171.000000171.779999169.800003171.660004171.6600048434800
321/02/2019GS198.970001199.449997195.050003196.360001196.3600012785900
421/02/2019FB161.929993162.240005159.589996160.039993160.03999315607800
##判断是否有缺失值
##使用isnull()和any()组合方法
#data_Date.isnull().any()##使用any()可以快速查看是否有缺失值
pd.isnull(data_Date).any()
Date         False
Symbol       False
Open         False
High          True
Low           True
Close        False
Adj Close    False
Volume       False
dtype: bool
##使用notnull()和all()组合方法
data_Date.notnull().all()
Date          True
Symbol        True
Open          True
High         False
Low          False
Close         True
Adj Close     True
Volume        True
dtype: bool

any():有True,则返回True,全False才返回False;
all():有False,则返回False,全True才返回True

#用NaN该列的均值代替NaN
data_Date.fillna(data_Date.mean())
DateSymbolOpenHighLowCloseAdj CloseVolume
021/02/2019AAPL171.800003172.369995170.300003171.059998171.05999817249700
121/02/2019JD24.820000176.459999173.68500124.27000024.27000013542600
221/02/2019BABA171.000000171.779999169.800003171.660004171.6600048434800
321/02/2019GS198.970001199.449997195.050003196.360001196.3600012785900
421/02/2019FB161.929993162.240005159.589996160.039993160.03999315607800

数据离散化

数据离散化(主要针对连续属性的数据离散化):在连续属性的值域上,将值域划分为若干个离散区间,最后用不同的符号或整数值代表落入到该区间的属性值的过程。简单点说就是将连续的数据分割多份,并给每份做上标记。
离散化的作用就是为了简化数据结构。一般的流程:
- 将数据进行分组:
- 自动分组:pd.qcut(data,q)–>q:组数;返回一个Series
- 自定义分组:pd.cut(data,[])–>[]:设定的区间;返回一个Series
- 对分组好的数据进行one-hot编码:
- pd.get_dummies(Series,prefix=None)–>prefix:前缀名

###有一组身高数据
height_info = pd.DataFrame({'age':[23,22,23,22],
                      'height':[170,180,176,162]},index=['Hajo','Mike','Joe','Shanel'])
height_info
ageheight
Hajo23170
Mike22180
Joe23176
Shanel22162
##现在按身高分为高,中,矮
##自动分组
sr1 = pd.qcut(height_info['height'],q=3)
sr1
Hajo      (161.999, 170.0]
Mike        (176.0, 180.0]
Joe         (170.0, 176.0]
Shanel    (161.999, 170.0]
Name: height, dtype: category
Categories (3, interval[float64]): [(161.999, 170.0] < (170.0, 176.0] < (176.0, 180.0]]
##自定义分组
sr2 = pd.cut(height_info['height'],[160,170,175,180])
sr2
Hajo      (160, 170]
Mike      (175, 180]
Joe       (175, 180]
Shanel    (160, 170]
Name: height, dtype: category
Categories (3, interval[int64]): [(160, 170] < (170, 175] < (175, 180]]
##分别对sr1和sr2进行one-hot 编码
d1 = pd.get_dummies(sr1)
d2 = pd.get_dummies(sr2)
print('sr1的one-hot编码:\n',d1)
print('sr2的one-hot编码:\n',d2)
sr1的one-hot编码:
         (161.999, 170.0]  (170.0, 176.0]  (176.0, 180.0]
Hajo                   1               0               0
Mike                   0               0               1
Joe                    0               1               0
Shanel                 1               0               0
sr2的one-hot编码:
         (160, 170]  (170, 175]  (175, 180]
Hajo             1           0           0
Mike             0           0           1
Joe              0           0           1
Shanel           1           0           0

以上全部就是本人学习Pandas库所整理的笔记,如有错误,欢迎指出!!!
数据资源链接:
链接:https://pan.baidu.com/s/1_OBCXvA8S4roQg4GK-JweA
提取码:7fb0

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值