jupyter入门之pandas

一. 什么是pandas

  • pandas是基于NumPy的一种工具 该工具是为了解决数据分析任务而创建的
  • pandas纳入了大量库及一些标准的数据模型,提供了高效的操作大型数据集所需要的工具
  • pandas提供了大量能使我们快速便捷地处理数据的函数与方法
  • 它是python成为强大而高效的数据分析环境的重要因素之一

导入

# 三剑客
import numpy
import pandas
from pandas import Series,DataFrame

二. Series

Series是一种类似于一维数组的对象,由下面两个部分组成

  • values: 一组数据 (ndarrary类型)
  • index: 相关的数据索引标签

1.创建

  • 由列表或numpy数组创建

    s1 = Series([1,2,3,4])
    >>> 0    1
      1    2
      2    3
      3    4
      dtype: int64
    s1 = np.array([1,2,3,4])
    >>> array([1, 2, 3, 4])

    特别地,由ndarray创建的是引用,而不是副本。对Series元素的改变也会改变原来的ndarray对象中的元素。(列表没有这种情况)

  • 由字典创建

    dic = {
      'name':'dancer',
      'age':19,
      'address':'hangzhou'
    }
    s3 = Series(data=dic)

2. 索引和切片

loc为显示切片(通过键),iloc为隐式切片(通过索引)

# 访问单个元素
s[indexname]
s.loc[indexname] 推荐
s[loc]
s.iloc[loc] 推荐

# 访问多个元素
s[[indexname1,indexname2]]
s.loc[[indexname1,indexname2]] 推荐
s[[loc1,loc2]]
s.iloc[[loc1,loc2]] 推荐

3. 基本概念

可以把Series看成一个定长的有序字典

可以通过shape(维度),size(长度),index(键),values(值)等得到series的属性

4.基本运算

  • 运算的原则就是索引对齐,如果缺失索引,对应位置补np.nan
  • NaN 是np.nan在pandas中的显示形式
  • 可以使用pd.isnull(),pd.notnull(),或自带isnull(),notnull()函数检测缺失数据
  • 可以使用isnull和any结合,来查看某一列或一行数据中是否存在缺失值
# 需求:提取s3对象中的所有非空数据
s3[s3.notnull()]
# 提取空值的索引
s3[s3.isnull()].index
# Sereis,对象可以使用一个与该对象等长的bool_list列表作为index访问数组元素
# 碰到True,就把对应位置的值返回
s3[[True,False,True,True,True,False]]
# name属性为Series对象添加列索引
s3.name = 'haha'

pandas会自动处理空值

add()
sub()
mul()
div()

Series之间的运算

  • 在运算中自动对齐不同索引的数据
  • 如果索引不对应,则补NaN
# fill_value设置空值的填充值
s1.add(s2,fill_value=0)

三. DataFrame

DataFrame是一个【表格型】的数据结构,可以看做是【由Series组成的字典】(共用同一个索引)。DataFrame由按一定顺序排列的多列数据组成。设计初衷是将Series的使用场景从一维拓展到多维。DataFrame既有行索引,也有列索引。

  • 行索引:index
  • 列索引:columns
  • 值:values(numpy的二维数组)

1. 创建

最常用的方法是传递一个字典来创建。DataFrame以字典的键作为每一【列】的名称,以字典的值(一个数组)作为每一列。

dic = {
    '张三':[150,150,150,300],
    '李四':[0,0,0,0]
}
DataFrame(data=dic,index=['语文','数学','英语','理综'])

也可以用下面代码实现创建

data = [[0,150],[0,150],[0,150],[0,300]]
index = ['语文','数学','英语','理综']
columns = ['李四','张三']
df = DataFrame(data=data,index=index,columns=columns)
>>> 
        李四  张三
        语文  0   150
        数学  0   150
        英语  0   150
        理综  0   300

此外,DataFrame会自动加上每一行的索引(和Series一样)。

同Series一样,若传入的列与字典的键不匹配,则相应的值为NaN。

2. 索引

(1) 对列进行索引

- 通过类似字典的方式
- 通过属性的方式

可以将DataFrame的列获取为一个Series。返回的Series拥有原DataFrame相同的索引,且name属性也已经设置好了,就是相应的列名。

(2) 对行进行索引

- 使用.ix[]来进行行索引
- 使用.loc[]加index来进行行索引
- 使用.iloc[]加整数来进行行索引

同样返回一个Series,index为原来的columns。

(3) 对元素索引的方法

- 使用列索引
- 使用行索引(iloc[3,1]相当于两个参数;iloc[[3,3]] 里面的[3,3]看做一个参数)
- 使用values属性(二维numpy数组)
# 索引行
df.loc[indexname] 推荐
df.iloc[loc]
# 索引列
df[columnname] 推荐
df.columnname
# 索引元素
df.loc[indexname].loc[columnname]
df[columnname].loc[indexname]
df.loc[indexname,columnname] 推荐

3. 切片

【注意】 直接用中括号时:

  • 索引表示的是列索引
  • 切片表示的是行切片
# 行切片
df[indexname1:indexname2] 
df.loc[indexname1:indexname2] 推荐
# 列切片
df.loc[:,columnname1:columnname2] 推荐
# 行列切片
df.loc[indexname1:indexname2,columnname1:columnname2] 推荐

df.iloc[indexloc1:indexloc2,columnloc1:columnloc2]

4. 运算

下面是Python 操作符与pandas操作函数的对应表:

Python Operator Pandas Method(s)
+ add()
- sub(), subtract()
* mul(), multiply()
/ truediv(), div(), divide()
// floordiv()
% mod()
** pow()
# df1与df2相加 空值以0填充
df1.add(df2,fill_value=0)
# DataFrame跟Series对象相加,fill_value不可用
df1.add(DataFrame(s1),fill_value=0)

# 求平均成绩
score1 = DataFrame(data=np.random.randint(0,100,size=(5,3)),
                   index=['dancer','lucy','tom','jack','rose'],
                  columns=['python','java','C++'])
score2 = DataFrame(data=np.random.randint(0,100,size=(5,3)),
                   index=['dancer','lucy','tom','jack','rose'],
                  columns=['python','java','C++'])

(score1 + score2)/2.

1) DataFrame之间的运算

同Series一样:

  • 在运算中自动对齐相同索引的数据
  • 如果索引不对应,则补NaN

2) Series与DataFrame之间的运算

【重要】

  • 使用Python操作符:以行为单位操作(参数必须是行),对所有行都有效。(类似于numpy中二维数组与一维数组的运算,但可能出现NaN)

  • 使用pandas操作函数:

    axis=0:以列为单位操作(参数必须是列),对所有列都有效。
    axis=1:以行为单位操作(参数必须是行),对所有行都有效。

  • axis=0(0 == index 行):以列为单位操作(参数必须是列),对所有列都有效。 axis=1(1 == columns 列):以行为单位操作(参数必须是行),对所有行都有效。

  • fill_value在df和series之间运算时,不能使用

四. 处理丢失数据

丢失数据有两种,

  • None
  • np.nan(NaN)

1. None

None是Python自带的,其类型为python object。因此,None不能参与到任何计算中。

type(None)
>>> NoneType

object类型,不能直接参与运算

而且object类型的运算比int类型的运算慢很多

2.np.nan(NaN)

type(np.nan)
>>> float

np.nan是浮点类型 可以参与计算,但计算结果为NaN

可以使用np.nan*()函数类计算nan,此时视nan为0

pandas中None与np.nan的操作

  • isnull()
  • notnull()
  • dropna(): 过滤丢失数据
  • fillna(): 填充丢失数据

(1)判断函数

  • isnull()
  • notnull()

过滤函数 dropna

# 默认过滤有空值的行
df1.dropna(axis=0)
# 过滤有空值的列
df1.dropna(axis=1)
# how参数指定过滤规则
# any  行或列中存在空值就过滤
# all  行或列中全部为空就过滤
df1.dropna(axis=0,how='all')

填充函数 fillna

df1.fillna(value=None,method=None,axis=0,limit=1)
# value  填充的值
# method 填充方式
  - ffill 向前
  - bfill 向后
  - pading
  - backfill
# axis   填充的轴
# limit  填充次数

五. pandas层次化索引

我们已经知道了Series和DataFrame

DataFrame是Series对象的扩展 那么为什么还要学层次化索引呢?

生活中的表格形式不是一成不变的

图中这种表如果使用DataFrame创建的话会相当麻烦

1.创建多层行索引

# 使用DataFrame创建
index1 = [['first','second'],['大米','白面','猪肉']]

index2 = [['first','大米'],['first','白面'],['first','猪肉'],['second','大米'],['second','白面'],['second','猪肉']]

index3 = [['first','first','first','second','second','second'],['大米','白面','猪肉','大米','白面','猪肉']]

data = np.random.randint(0,200,size=(6,4))
columns = ['dancer','lucy','tom','jerry']
df = DataFrame(data=data,index=index3,columns=columns)

显然 重复写索引是很麻烦的事

这里我们可以使用pandas的显示构造 pandas.MultiIndex

它提供了三种方法

pandas.MultiIndex.from_array

mindex3 = pd.MultiIndex.from_arrays(index3,names=('季度','品类'))
df = DataFrame(data=data,columns=columns,index=mindex3)

pandas.MultiIndex.from_tuple

mindex2 = pd.MultiIndex.from_tuples(index2,names=('季度','品类'))
df2 = DataFrame(data=data,index=mindex2,columns=columns)

pandas.MultiIndex.from_product

# 推荐
mindex3 = pd.MultiIndex.from_product(index1,names=('季度','品类'))
df3 = DataFrame(data=data,index=mindex3,columns=columns)

2. 多层列索引

columns = pd.MultiIndex.from_product([['first','seoncd'],['大米','白面','猪肉']])
data = np.random.randint(0,100,size=(4,6))
index = df3.columns
df4 = DataFrame(data=data,index=index,columns=columns)
df4
>>> 季度      first       second
品类  大米  白面  猪肉  大米  白面  猪肉
dancer  50  94  71  46  72  22
lucy    94  61  96  15  76  12
tom     72  97  63  18  8   22
jerry   98  5   73  84  84  31

3. 多层索引对象的索引与切片操作

【重要】对于Series来说,直接中括号[]与使用.loc()完全一样,推荐使用.loc中括号索引和切片。

index = pd.MultiIndex.from_product([['期中','期末'],['语文','数学','英语']])
data = np.random.randint(0,150,size=6)
s1 = Series(data=data,index=index)
s1
>>> 期中  语文    112
          数学    145
          英语     59
    期末  语文    128
          数学     91
          英语    129
    dtype: int32

1) 索引

# 把多级索引变成单级索引访问
s1.loc['期中'].loc['语文']
s1['期中'].iloc[0]
s1.loc['期中','语文']
>>> 结果都为 112

2)切片

  • 可以直接使用iloc对value切片 但可读性不高

  • 多级索引切片 可使用显示索引

    
    # 期中考试的语文数学成绩
    
    s1.loc['期中'].loc['语文':'数学']
    
    # 编程单级索引进行列切片 (不能跨区)
    
    df['期中'].loc[:,'语文':'数学']
  • 不能跨区切片 比如获取期中到期末的语文成绩

那如果我们需要进行跨区切片该怎么办呢?

这里引入一个stack概念(索引的堆)

4. 索引的堆(stack)

  • stack()
  • unstack()
  • level 多级索引从外向内 依次的编号是0.1.2…
  • 使用stack()时, level设置为几,就把哪一级索引消失
  • 使用unstack()的时候,level等于哪一个,哪一个就消失,出现在列里
  • 注意不要在变化的途中变成了Series对象

六. pandas的拼接操作

pandas的拼接分为两种:

  • 级联:pd.concat, pd.append
  • 合并:pd.merge, pd.join

回顾 numpy的级联

n1 = np.random.randint(0,10,size=(3,3))
n2 = np.random.randint(10,20,size=(3,2))
np.concatenate((n1,n2),axis=1)
>>> array([[ 4,  0,  4, 14, 17],
        [ 5,  9,  2, 10, 17],
        [ 2,  3,  1, 15, 11]])

1. 使用pd.concat()级联

# 注:create_DF为封装的一个用于生成DataFrame对象的函数 
#第一个参数是index 第二个参数是column
df1 = create_DF(list('12345'),list('ABCDE'))
df2 = create_DF(list('12345'),list('BCDEF'))
# 两个DataFrame对象级联操作
pd.concat((df1,df2),axis=1)

Create_DF

def create_DF(index,columns):
    return DataFrame({j:[j+i for i in index] for j in columns},index=index)
  • pandas中,级联允许形状不同,缺失的索引补充NaN

  • pandas使用pd.concat函数,与np.concatenate函数类似,只是多了一些参数:

    objs
    axis=0
    join=’outer’
    join_axes=None
    ignore_index=False

  • 索引没有特定含义的时候,可以使用如下方法处理索引重复的问题

    pd.concat((df1,df2),ignore_index=True)
  • 索引有特定含义,可以引入keys参数,对两张表做分区说明

    pd.concat((df1,df2),keys=['上学期','下学期'])
  • 应该更多的采用外连接来级联,保留更多的原始数据

    • inner内连接,取交集

    • outer外连接, 取并集

    pd.concat((df1,df2),join='outer')

1) pandas与series级联

# 使用级联处理
s = Series(data=[100,99],index=['张三','李四'],name='计算机')
# pandas可以直接跟series对象进行级联
pd.concat((score,s),axis=1)

2) 不匹配级联

不匹配指的是级联的维度的索引不一致。例如纵向级联时列索引不一致,横向级联时行索引不一致

有3种连接方式:

  • 外连接:补NaN(默认模式)

  • 内连接:只连接匹配的项

  • 连接指定轴 join_axes

3) append()函数

由于在后面级联的使用非常普遍,因此有一个函数append专门用于在后面添加

注意:append函数只是沿着axis=0的方向进行级联

2.使用pd.merge()合并

mergeconcat的区别在于,merge需要依据某一共同列来进行合并

使用pd.merge()合并时,会自动根据两者相同column名称的那一列,作为key来进行合并。

注意每一列元素的顺序不要求一致

  • merge的合并也分一对一 多对一 多对多 就是合并相同columns

1) 一对一合并

以手机型号为合并基准

2) 多对一合并

同样以手机型号为基准

3) 多对多合并

当有多个相同列时 可以以其中任何一个相同列为基准合并 也可以多个相同列为基准

4) key的规范化

1. 如果两个表中,只有一列内容是有重复的,就参考这一列进行合并
2. 默认的合并方式,只取交集
3. how 设置合并的参考列
4. 合并就是以列为参考的,不是以行

pd.merge(table1,table2,how='right')

5. 使用on=显式指定哪一列为key,当有多个key相同时使用
6. 两张表中不存在相同的列表签,可以使用left_on和right_on来显示制定合并参考列
7. 合并之后两列都会保留,可以使用drop函数删除没用的列

pd.merge(table2,table5,left_on='手机型号',right_on='型号').drop(labels=['型号'],axis=1)
# 以表的行索引为合并参考
# 设置left_index或right_index为True
pd.merge(table2,table6,left_on='手机型号',right_index=True)
  • 数值型数据,尽量采用级联而不是合并
  • 字符串型数据,可以使用合并
  • 一旦数值出现重复值,就会导致业务逻辑变成1对多或者对对多的关系

5) 内合并与外合并

  • 内合并:只保留两者都有的key(默认模式)

  • 外合并 how=’outer’:补NaN

  • 左合并、右合并:how=’left’,how=’right’,

6)列冲突的解决

  • 当列冲突时,即有多个列名称相同时,需要使用on=来指定哪一个列作为key,配合suffixes指定冲突列名
  • 可以使用suffixes=自己指定后缀

猜你喜欢

转载自blog.csdn.net/weixin_42042680/article/details/80684415