Pandas数据分析

Pandas学习

文章目录

(一).前言:

Pandas是建立在Numpy数据结构上的,尤其时它的Series 和Dataframe对象,为数据科学家们处理那些消耗大量时间的"数据清理"任务提供了捷径.
下面我将重点介绍Series ,Dataframe和其他数据结构的高效使用方法.

(二).Pandas的安装:

在安装Pandas之前首相要确保你已经安装了Numpy,详细的安装方法,请参考Pandas官方文档(http://pandas.pydata.org/).

(三).Pandas对象简介:

三个基本数据结构:Series,DataFrame,和Index.

1.Pandas的Series对象

1.1 Series是通用的Numpy数组

Series对象和一维Numpy数组基本可以等价交换,本质差异就是索引:
Numpy通过隐式定义的整数索引获取数值,而Series使用一种显式定义的索引与数值关联,意思就是索引不单单可以是整数,还可以是任意想要的类型,例如:字符串,浮点数等等.

data = pd.Series([0.25,0.5,0.75,1.0],index=['a','b','c','d'])
print(data)

输出结果:

a    0.25
b    0.50
c    0.75
d    1.00
dtype: float64

也可以使用不连续或者不按顺序的索引:

data = pd.Series([0.25,0.5,0.75,1.0],index=[2,5,3,7])
print(data)

输出结果:

2    0.25
5    0.50
3    0.75
7    1.00
dtype: float64
进程已结束,退出代码为 0

1.2. Series是特殊的字典

Series其实是一种将类型键映射到类型值的数据结构.
我们可以直接使用字典创建一个Series对象:

area_dict={'California':423967,'Texas':605662,'New York':141297,'Florida':170312,'Illinois':149995}
area=pd.Series(area_dict)
print(area)

输出结果:

California    423967
Texas         605662
New York      141297
Florida       170312
Illinois      149995
dtype: int64

用字典创建Series时,典型的字典数值获取方式仍然有效

 print(population['California'])

1.3. 创建Series对象

上述几种创建方式都是这样的形式

pd.Series(data,index=index)

其中index是一个可选参数,data参数支持多种数据类型.
例如:data可以是一个Numpy数组

pd.Series([2,4,6])

输出结果:

0    2
1    4
2    6
dtype: int64

data也可以是一个标量,创建时会重复填充到每一个索引上:

pd.Series(5,index=[100,200,300])

输出结果:

100    5
200    5
300    5
dtype: int64

data还可以是一个字典,index默认是排序的字典键:

pd.Series({2:'a',1:'b',3:'c'})

输出结果:

2    a
1    b
3    c
dtype: object

每一种形式都可以通过显式指定索引:

pd.Series({2:'a',1:'b',3:'c'},index=[3,2])

输出结果:

3    c
2    a
dtype: object

需要注意的是,Series只会保留显式定义的键值对.

2. Pandas的DataFrame对象

Pandas的另一个基础数据结构就是Dataframe.也可以作为Numpy的一个通用类型数组,也可以看作特殊的字典.

2.1.DataFrame是通用的Numpy数组

前面我们了解到了,Series是有灵活的行索引的一维数组,那么DaraFrame就可以看做,是一种既具有灵活的行索引,还具有灵活的列名的二维数组.

population_dict={'California':38332521,'Texas':26448193,'New
York':19651127,'Florida':19552860,'Illinois':12882135}

population=pd.Series(population_dict)

area_dict={'California':423967,'Texas':605662,'New York':141297,'Florida':170312,'Illinois':149995}

area=pd.Series(area_dict)

states=pd.DataFrame({'population':population,'area':area})
print(states)

输出结果:

            population    area
California    38332521  423967
Texas         26448193  605662
New York      19651127  141297
Florida       19552860  170312
Illinois      12882135  149995
进程已结束,退出代码为 0

可以看到DataFrame类似于二维数组,具有列名的对象
和Series一样,DataFrame也有index属性可以获取索引标签:

print(states.index)

输出结果:

Index(['California', 'Texas', 'New York', 'Florida', 'Illinois'], dtype='object')

另外,DataFrame还有一个columns属性,是存放列标签的index对象:

print(states.columns)

输出结果:

Index(['population', 'area'], dtype='object')

2.2. DataFrame是特殊的字典

DataFrame是一种一列映射一个Series值的数据.例如:通过area可以返回包含列属性的Series对象:

print(states['area'])

输出结果:

California    423967
Texas         605662
New York      141297
Florida       170312
Illinois      149995
Name: area, dtype: int64
进程已结束,退出代码为 0

注意:在Numpy二维数组里面,data[0]是返回第一行,而DataFrame中data[‘col0’]是返回第一列

2.3.创建DataFrame对象

2.3.1通过单个Series创建.

DataFrame是多个Series对象的集合,可以用单个Series来创建一个单列的DataFrame:

population_dict={'California':38332521,'Texas':26448193,'New York':19651127,'Florida':19552860,'Illinois':12882135}
population=pd.Series(population_dict)
states=pd.DataFrame({'population':population,'area':area})
data=pd.DataFrame(population,columns=['population'])
print(data)

输出结果:

            population
California    38332521
Texas         26448193
New York      19651127
Florida       19552860
Illinois      12882135
进程已结束,退出代码为 0

2.3.2 通过字典列表创建:

data=[{'a':i,'b':i*2}
          for i in range(0,3)]
data01=pd.DataFrame(data)
print(data01)

输出结果:

   a  b
0  0  0
1  1  2
2  2  4

即使字典中的有些键不存在,Pandas也会用NaN来表示:

data=pd.DataFrame([{'a':1,'b':2},{'b':3,'c':4,'d':5}])
print(data)

输出结果:

     a  b   c   d
0  1.0  2  NaN  NaN
1  NaN  3  4.0  5.0

2.3.3 还有一种就是上述2.1.所示例的创建方法.

通过Series对象构成的字典

2.3.4 通过Numpy二维数组创建.

假如有一个二维数组,就可以创建一个指定行索引的DataFrame对象,如果不指定,那么就默认是整数索引值.

data01=pd.DataFrame(np.random.rand(3,2),index=['a','b','c'],columns=['num1','num2'])
print(data01)

输出结果:

#这个是指定行索引
       num1      num2
a  0.558924  0.558841
b  0.294003  0.305038
c  0.625494  0.760208
#这个是未指定行索引
       num1      num2
0  0.065357  0.172990
1  0.831366  0.892077
2  0.726851  0.422833
进程已结束,退出代码为 0

2.3.5 通过Numpy结构化数组创建.

A=np.zeros(3,dtype=[('A','i8'),('B','f8')])
print(A)
a=pd.DataFrame(A)
print(a)

输出结果:

[(0, 0.) (0, 0.) (0, 0.)]
   A    B
0  0  0.0
1  0  0.0
2  0  0.0
进程已结束,退出代码为 0

3.Pandas的index对象

index是一个很有趣的数据结构,我们可将它看做成一个有序集合,或者不可变数组.

3.1.将index看做成一个不可变数组

index许多操作都很像数组.我们试着用一个简单的整数列表来创建一个index对象:

ind=pd.Index([2,3,5,7,11])

然后对其进行简单的数组操作:

#取值
print(ind[1])
#切片
print(ind[::2])

输出结果:

3
Int64Index([2, 5, 11], dtype='int64')

Index还有许多与数组相类似的属性:

print(ind.shape,ind.size,ind.ndim,ind.dtype)

输出结果:

(5,) 5 1 int64

Index对象与数组不同之处在于,Index对象的索引是不可变的
这个特点的好处就是,可以避免因粗心大意而修改索引值的副作用,多个DataFrame与数组之间进行索引共享时更加安全.

3.2.将Index看作有序集合

Index遵循python标准库集合用法,包括并集,交集,差集等

indA=pd.Index([1,2,3,4,5])
indB=pd.Index([3,4,5,6,7])
print(indA&indB)#交集
print(indA|indB)#并集
print(indA^indB)#差集

输出结果:

Int64Index([3, 4, 5], dtype='int64')#交集
Int64Index([1, 2, 3, 4, 5, 6, 7], dtype='int64')#并集
Int64Index([1, 2, 6, 7], dtype='int64')#差集

这些操作还可以用调用对象方法来实现例如:indA.intersection(intB)

(四)数据取值与选择

1 Series的数据选择方法

1.1把Series当作字典

和字典一样series提供了键值对的映射:

import pandas as pd
data=pd.Series([1,2,3,4],index=['a','b','c','d'])
print(data['a'])

输出结果:

1

还可以用字典的语法来调整Series
增添新的索引值来扩展Series

data['e']=5
print(data)

输出结果:

a    1
b    2
c    3
d    4
e    5
dtype: int64
进程已结束,退出代码为 0

1.2.同理也可以将Series当作一维数组

1.3. 使用索引器:loc,iloc和ix(不常用).

由于上述方法容易混淆显式索引和隐式索引,毕竟整数索引就很容易混淆
所以Pandas就提供了索引器属性.

1.3.1 第一种就是loc属性,表示取值和切片都是显式索引

import pandas as pd
data=pd.Series([1,2,3,4],index=['a','b','c','d'])
print(data.loc['a'])
print(data.loc['a':'d'])

输出结果:

1
a    1
b    2
c    3
d    4
dtype: int64
进程已结束,退出代码为 0

1.3.2第二种就是iloc属性表示都用的是隐式索引

data=pd.Series([1,2,3,4],index=['a','b','c','d'])
print(data.iloc[1])
print(data.iloc[0:3])

输出结果:

2
a    1
b    2
c    3
dtype: int64

1.3.3第三种属性就是ix

pandas版本0.20.0及其以后版本中,ix已经不被推荐使用
这个属性就是前两种属性的混合形式,我强烈建议使用前两种索引器,避免误用索引,也是自己的代码更容易理解.

2.DataFrame的数据选择方法

先用字典的形式创建一个DataFrame对象;

import pandas as pd
num01=pd.Series({'a':11,'b':22,'c':33})
num02=pd.Series({'a':1,'b':2,'c':3})
num=pd.DataFrame({'num01':num01,'num02':num02})
print(num)

输出:

   num01  num02
a     11      1
b     22      2
c     33      3

2.1将DataFrame看作字典

这个和Series是一样的,不多做解释.

2.2将DataFrame理解为加强版的二维数组

这样我们就可以对它进行更多操作,例如:
转置: num.T
取单行:

print(num.values[0])

输出:

[11  1]

取单列:

print(num.num01)

输出:

a    11
b    22
c    33
Name: num01, dtype: int64

2.3使用loc,iloc

print(num.iloc[:3, :2])
print(num.loc[:'c',:'num02'])

输出:

   num01  num02
a     11      1
b     22      2
c     33      3
   num01  num02
a     11      1
b     22      2
c     33      3

任何一种方法都可调整数据,这一点和Numpy的常用方法是相同的:

num.iloc[0]=90

输出:

   num01  num02
a     90     90
b     22      2
c     33      3

(五)Pandas数值运算方法

Pandas不仅继承了Numpy的基本运算方法,也实现了一些高效的技巧.

1.通用函数:保留索引

让我们创建一个简单的Series和DataFrame来演示:

import numpy as np
import pandas as pd
rng=np.random.RandomState(42)
ser=pd.Series(rng.randint(0,10,4))
df=pd.DataFrame(rng.randint(0,10,(3,4)),columns=['A','B','C','D'])
print(ser)
print(df)

输出;

0    6
1    3
2    7
3    4
dtype: int32
   A  B  C  D
0  6  9  2  6
1  7  4  3  7
2  7  2  5  4
进程已结束,退出代码为 0

对两个对象使用Numpy通用函数,生成的是另一个保留索引的Pandas对象:

print(np.exp(ser))
print(np.sin(df))

输出:

0     403.428793
1      20.085537
2    1096.633158
3      54.598150
dtype: float64
          A         B         C         D
0 -0.279415  0.412118  0.909297 -0.279415
1  0.656987 -0.756802  0.141120  0.656987
2  0.656987  0.909297 -0.958924 -0.756802

进程已结束,退出代码为 0

2.通用函数:索引对齐

2.1 Series索引对齐

看一个例子:假如你要整合两个数据源的数据,其中一个是美国面积最大的三个州的面积数据,另一个是美国人口最多的三个州的人口数据.

import pandas as pd
area=pd.Series({'Alasksa':1723337,'Texas':26448193,'California':21565132},name='area')
population=pd.Series({'California':3813515,'Texas':3215631,'New York':1565484},name='population')

我们试着用area除以population看看会得到什么结果:

print(area/population)

输出:

Alasksa            NaN
California    5.654923
New York           NaN
Texas         8.224884
dtype: float64
进程已结束,退出代码为 0

得到个两者的并集,缺失的索引Pandas会自己用NaN填充.

2.1 DataFrame索引对齐

我们先创建两个DataFrame对象:

rng=np.random.RandomState(42)
A=pd.DataFrame(rng.randint(0,20,(2,2)),columns=list('AB'))
B=pd.DataFrame(rng.randint(0,10,(3,3)),columns=list('BAC'))
print(A)
print(B)

输出:

    A   B
0   6  19
1  14  10
   B  A  C
0  7  4  6
1  9  2  6
2  7  4  3
进程已结束,退出代码为 0

两者相加;

      A     B   C
0  10.0  26.0 NaN
1  16.0  19.0 NaN
2   NaN   NaN NaN
进程已结束,退出代码为 0

你会发现,即使两个对象的索引是不同顺序的,结果的索引是按照顺序排列
我们用fill_value参数自定义缺失值,这里我将用A的所有值的均值来填充缺失值:

#先将A用stack把二维压缩成一维数组再进行计算均值
fill=A.stack().mean()
C=A.add(B,fill_value=fill)
print(C)

输出:

       A      B      C
0  10.00  26.00  18.25
1  16.00  19.00  18.25
2  16.25  19.25  15.25
进程已结束,退出代码为 0

表3-1列举了Pandas的运算方法:
在这里插入图片描述

3.DataFrame与Series的运算

我们经常需要对一个DataFrame和一个Series进行计算,行列式对齐方式与之前类似,也就是说,DataFrame和一个Series计算就是Numpy中的二维数组和一个一维数组进行计算.

import numpy as np
import pandas as pd
rng=np.random.RandomState(42)
A=rng.randint(10,size=(3,4))
df=pd.DataFrame(A,columns=list('QWER'))
fd=df.iloc[0,::2]
print("df:\n%s"%df)
print("fd:\n%s"%fd)
print(df-fd)

输出:

df:
   Q  W  E  R
0  6  3  7  4
1  6  9  2  6
2  7  4  3  7
fd:
Q    6
E    7
Name: 0, dtype: int32
     E    Q   R   W
0  0.0  0.0 NaN NaN
1 -5.0  0.0 NaN NaN
2 -4.0  1.0 NaN NaN

进程已结束,退出代码为 0

这些行列索引的自动对齐说明Pandas在运算时会保留这些数据内容,从而避免维度不一致时的运算错误.

(六)处理缺失值

本节涉及的处理方法有三种方式:‘null’,‘NaN’,‘NA’.

1.选择处理缺失值的方法

在数据表或者DataFrame中处理法一般分为两种:
第一种:通过覆盖全局的掩码表示缺失值
另一种:用一个标签值表示缺失值.
(一)掩码方法中:掩码可能是一个与原数组维度相同的完整布尔类型数组,也可能是用一个0或1来表示缺失值的局部状态.
(二)标签法中标签值可能是具体的数据,也可能是极少出现的形式.
使用者两种方法都先要综合考虑:
使用单独的掩码数组会额外出现一个布尔类型数组,从而增加储存于计算负担…
使用标签法缩小了可以被表示为有效值的范围可能需要在Gpu或Cpu算桉树逻辑单元中增加额外的计算逻辑,通常使用的NaN也不能表示所有数据类型.

2. Pandas的缺失值

2.1 None:Python对象类型的缺失值

由于None是Python的对象,所以它只能用作为’object’数组类型的缺失值
如果你用一个 包含None的数组进行累计运算,比如min(),sum()等,那么通常会出现类型错误.

2.2 NaN数值类型的缺失值

NaN全称为:“Not a Number”(不是一个数字),是一种按照IEEE浮点数标准射击,在任何系统中都兼容的特殊浮点数.
你可以把NaN看作是一种数据病毒,他将与它接触的数据同化,无论NaN进行何种运算,得到的结果都是NaN.
NaN是一种特殊的浮点数.

3.NaN与None的差异

虽然两者各有各的用处但是Pandas有时候会将他们看作是可以等价交换的
,在适当的时候将两者进行替换:

import numpy as np
import pandas as pd
A=pd.Series([1,np.nan,2,3,None])
print(A)

输出:

0    1.0
1    NaN
2    2.0
3    3.0
4    NaN

除了将整型数组的缺失值强制转换为浮点数,Pandas还会自动将None转换为NaN

4.处理缺失值

Pandas提供了一些方法来发现,剔除,替换数据结构中缺失值,主要包括以下几种:
isnull()创建一个布尔类型的掩码标签缺失值.
notnull()与isnull()操作相反.
dropna()返回一个剔除缺失值的数据.
fillna()返回一个填充了缺失值的数据副本.

5.层级索引

5.1多级索引Series

Pandas的MultiIndex类型提供了丰富的操作方法
我们先用元组创建一个数据-----漂亮国各个州在两个不同年份的数据:

import numpy as np
import pandas as pd
index=[('California',2000),('California',2010),
('New York',2000),('New York',2010),('Texas',2000),
       ('Texas',2010)]
populations=[132,12,554,234,127,232]
A=pd.Series(populations,index=index)
print(A)

输出:

(California, 2000)    132
(California, 2010)     12
(New York, 2000)      554
(New York, 2010)      234
(Texas, 2000)         127
(Texas, 2010)         232
dtype: int64

进程已结束,退出代码为 0

当我们用了多级索引后:

index=pd.MultiIndex.from_tuples(index)
A=A.reindex(index)#重置一下索引
print(A)

输出:

California  2000    132
            2010     12
New York    2000    554
            2010    234
Texas       2000    127
            2010    232
dtype: int64

进程已结束,退出代码为 0

可以发现有些行没有了第一列数据,这个其实就是多级的表现形式,每个空格与上面的索引相同.
现在我们就可以直接使用第二列的索引来获取2010 年的所有数据,和之前的切片用法一样:

print(A[:,2010])

输出:

California     12
New York      234
Texas         232
dtype: int64

进程已结束,退出代码为 0

6.高维数据的多级索引

unstack()方法可以快速将一个多级索引的Series转化为一个普通索引的DataFrame

import numpy as np
import pandas as pd
index=[('California',2000),('California',2010),
('New York',2000),('New York',2010),('Texas',2000),
       ('Texas',2010)]
populations=[132,12,554,234,127,232]
A=pd.Series(populations,index=index)
index=pd.MultiIndex.from_tuples(index)
A=A.reindex(index)#重置一下索引
print(A)
A=A.unstack()
print(A)

输出:

California  2000    132
            2010     12
New York    2000    554
            2010    234
Texas       2000    127
            2010    232
dtype: int64
            2000  2010
California   132    12
New York     554   234
Texas        127   232

进程已结束,退出代码为 0

我们可以用一维的Series来表示二维的数据,那么我们就可以使用Series和DataFrame的组合来表示三维或者更高维的数据.

7,多级索引的创建方法

7.1显式地创建多级索引

你可以使用pd.Multiindex中的类方法更加灵活地构建多级索引.
例如:

B=pd.MultiIndex.from_arrays([['a','a','b','b'],[1,2,1,2]])
print(B)

输出:

MultiIndex([('a', 1),
            ('a', 2),
            ('b', 1),
            ('b', 2)],)

进程已结束,退出代码为 0

也可以用两个索引的笛卡尔积创建MulitiIndex:

B=pd.MultiIndex.from_product([['a','b'],[1,2]])

你也可以直接提供levels和labels.
在创建Series或者DataFrame时候可以将这些作为index参数,或通过reindex方法重置更新索引.

7.2多级索引的等级名称

你可以在前面任意一个MultiIndex构造器中通过names参数设置更改等级名称,也可以创建之后通过索引的names属性来修改名称:

import pandas as pd
index=[('California',2000),('California',2010),
('New York',2000),('New York',2010),('Texas',2000),
       ('Texas',2010)]
populations=[132,12,554,234,127,232]
A=pd.Series(populations,index=index)
index=pd.MultiIndex.from_tuples(index)
A=A.reindex(index)#重置一下索引
A.index.names=['pleace','age']
print(A)

输出:

pleace      age 
California  2000    132
            2010     12
New York    2000    554
            2010    234
Texas       2000    127
            2010    232

在处理复杂数据的时候更改索引名字是个好办法.

7.3多级列索引

既然有多级行索引那就一定有多级列索引;

#多级行列索引
index=pd.MultiIndex.from_product([[2013,2014],[1,2]],names=['year','visit'])
columns=pd.MultiIndex.from_product([['Bob','Guido','Sue'],['HR','Temp']],names=['subject','type'])

#模拟数据
data=np.round(np.random.rand(4,6),1)
data[:,::2]*=10
data +=data

#创建DataFrame
health_data=pd.DataFrame(data,index=index,columns=columns)
print(health_data)

输出:

subject      Bob      Guido        Sue     
type          HR Temp    HR Temp    HR Temp
year visit                                 
2013 1       6.0  1.2   6.0  1.6  12.0  0.2
     2      12.0  0.4   8.0  0.8   6.0  0.8
2014 1       8.0  0.4   8.0  0.2   6.0  1.0
     2      16.0  1.4   8.0  0.4   2.0  1.0

进程已结束,退出代码为 0

上面创建了一个简易的四维数据,分别为被检查人的姓名,检查项目,检查年份,检查次数.可以在列索引第一级查询姓名,从而获取包含一个人的全部检查信息的DataFrame:
例:

print(health_data['Guido'])

输出:

type          HR  Temp
year visit            
2013 1      18.0   0.2
     2      18.0   1.2
2014 1       8.0   1.8
     2       8.0   0.2

进程已结束,退出代码为 0

如果想获取包含多种标签的数据,需要通过多个维度的多次查询才能实现,这时使用多级行列索引进行查询会非常方便.

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞行模式、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值