一 pandas简介

pandas是一个强大的Python数据分析的工具包, 是基于NumPy构建的
pandas的主要功能

  • 具备对其功能的数据结构DateFrame Series
  • 集成时间序列功能
  • 提供丰富的数学运算和操作
  • 灵活处理缺失数据

安装方法: pip install pandas
引用方法:import pandas as pd

二 pands的Series对象

1 Series 一维数据对象

Seriaes是一种类似于一位数组的对象, 由一组数据和一组与之相关的数据标签(索引)组成新的二维数组
创建方式:

pd.Series([4,7,-5,3])
pd.Series([4,7,-5,3], index=['a', 'b', 'c', 'd'])
pd.Series({'a':1, 'b':2})
pd.Series(0, index=['a','b','c','d'])

获取值数组和索引数据: values属性和index属性
Series比较像列表(数组)和字典的结合体

2 Series使用特性

Series支持array的特性(下标):

  • 从ndarray创建Series:Series(arr)
  • 与标量运算: sr*2
  • 两个Series运算: sr1+sr2
  • 索引:sr[0], sr[[1,2,4]]
  • 切片:sr[0:2]
  • 通用函数:np.abs(sr)
  • 布尔值过滤: sr[sr>0]

Series支持字典的特性(标签):

  • 从字典创建Series: Series(dic)
  • in运算: 'a' in sr
  • 键索引:sr['a'], sr[['a','b', 'd']]

3 Series整数索引问题

整数索引的pandas对象往往会使新手抓狂的地方
例如:

  • sr = pd.Series(np.arange(4.))
  • sr[-1]

如果索引是整数类型,则根据整数进行下标获取值时总是面向标签的。
解决方法: loc属性(将索引解释为标签)和iloc属性(将索引解释为下标)
如:sr2.loc[10] sr2.iloc[-1]

4 Series数据对齐

例:

  • sr1 = pd.Series([12,23,34], index=['c','a','d'])
  • sr2 = pd.Series([11,20,10], index=['d', 'c', 'a'])
  • sr1+sr2

pandas在进行两个Series对象的运算时,会按索引进行对齐然后计算

  • a:33
  • c:32
  • d:45

如何使用结果再索引'b'处的值为11, 在索引‘d’处的值为34?

  • 灵活的算术方法: add, sub, div, mul
  • sr1.add(sr2, fill_value=0)

5 Series缺失值处理

缺失数据:使用NaN(Not a Number) 来表示缺失数据。其值等于np.nan。内置的None值也会被当做NaN处理

sr.isnull()       Nan返回True
sr.notnull()      Nan但会False
sr.dropna()       删除索引Nan
sr.fillna(0)      填充所有的nan

 过滤缺失数据:sr.dropna() 活 sr[data.notnull()]

 填充缺失数据:fillna(0)

三 Pandas之DataFrame-二维数据对象

DataFrame是一个表格型的数据结构, 含有一组有序的列。DataFrame可以被看做是由Series组成的字典,并且共用一个索引

创建方式:

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

csv文件读取与写入:

df.read_csv('filename.csv')
df.to_csv()

DataFrame常用的属性:

index         获取索引 行索引
T             转置  行变成列 列变成行
columns       获取列索引
values        获取值数组
describe()    获取快速统计

 DataFrame索引和切片:

索引:

  - df[col] df[[c1,c2]]  # 取列

  - df.loc[index]         # 取列

  - df.loc[index, col]  # 取元素

切片

  - df[a:b]  # 切行

  - df.loc[:, a:b]  # 切列

DataFrame是一个二维数据类型,所以有行索引和列索引。
DataFrame同样可以通过标签和位置两种方法进行索引和切片。
loc属性和iloc属性:

  • 使用方法: 逗号隔开,前面是行索引, 后面是列索引
  • 行/列索引部分可以是常规索引,切片,布尔索引,花式索引任意搭配

示例:

# 先取列再取行
df['one']['a']
# 推荐使用loc
df.loc['a', 'one']
# 查看一行数据
dc.loc['a', :]

DataFrame数据对齐与缺失数据:

DataFrame对象在运算时, 同样会进行数据对齐, 其行索引和列索引分别对齐
DataFrame处理缺失数据的相关方法:

dropna(axis=0, where='any', ...)  # 当行所有都是Nan才删除dropna(how='any') 
fillna()
isnull()
notnull()

四 pandas其他常用方法

常用函数

mean(axis=0, skipna=False)           对列(行)求平均数
sum(axis=1)                          对列(行)求和
sort_index(axis, ..., ascending)     对列(行)索引排序
sort_values(by,axis, ascending)      安某一列(行)的值排序
reset_index(drop=true)          重新处理index NumPy的通用函数同样适用于pandas

五 pandas-时间对象处理

时间序列类型:

  • 时间戳:特定时刻
  • 固定时刻: 如2017年7月
  • 时间间隔:起始时间-结束时间

Python标准库处理时间对象:datetime

灵活处理时间对象: dateutil

dateutil.parser.parse()

成组处理时间对象:pandas

pd.to_datetime()

生成时间范围:date_range

  • start 开始时间
  • end 结束时间
  • periods 时间长度
  • freq 时间频率, 默认为'D', 可选H(our), W(eek), B(usiness), S(emi0)M(onth), (min)T(es), S(econd), A(year)
pd.date_range('2010-01-01', '2010-5-1')

pandas-时间序列:

时间序列就是以时间对象为索引的Series或DataFrame
datetime对象作为索引时是存储在DatetimeIndex对象中的。
时间序列特殊功能:

  • 传入“年”或“年月”作为切边方式
  • 传入日期范围作为切片方式
  • 丰富的函数支持: resample(), truncate()

 六  pandas-文件处理

数据文件常用格式: csv(以某间隔符分割数据)

pandas读取文件: 从文件名,URL,文件对象中加载数据

read_csv     默认分隔符为逗号
read_table   默认分隔符为制表符

read_csv, read_table函数主要参数:

sep               指定分隔符,可用正则表达式如"\s+"
header=None       指定文件无列名
name              指定列名
index_col         指定某列为索引
skip_row          指定跳过某些行
na_values         指定某些字符串表示缺失值
parse_dates       指定某些列是否被解析为日期,类型布尔值或列表

pandas写入csv文件: to_csv函数:

sep            指定文件分隔符
na_rep         指定缺失值转换的字符串,默认为空字符串
header=False   不输出列名一行
index=False    不输出索引一列
cols           指定输出的列,传入列表

 七 Pands实现数据清洗

处理丢失数据

有两种丢失数据:

  • None
  • np.nan(NaN)

1. None

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

2. np.nan(NaN)

np.nan是浮点类型,能参与到计算中。但计算的结果总是NaN。

1) pandas中None与np.nan都视作np.nan

创建dataframe

import numpy as np
import pandas as pd

df = pd.DataFrame(data=np.random.randint(10, 50, size=(8,8)))
df

    0    1    2    3    4    5    6    7
0    29    36    36    30    43    17    20    33
1    43    21    49    19    30    33    49    10
2    11    44    13    45    20    10    29    35
3    10    34    45    12    29    26    10    15
4    11    11    49    15    48    26    49    36
5    26    45    44    28    42    33    43    45
6    29    46    42    30    45    15    29    24
7    28    23    26    28    29    15    18    32

将某些数组元素赋值为nan

df.iloc[1,3] = None
df.iloc[2,2] = None
df.iloc[4,2] = None
df.iloc[6,7] = np.nan
df

0    1    2    3    4    5    6    7
0    29    36    36.0    30.0    43    17    20    33.0
1    43    21    49.0    NaN    30    33    49    10.0
2    11    44    NaN    45.0    20    10    29    35.0
3    10    34    45.0    12.0    29    26    10    15.0
4    11    11    NaN    15.0    48    26    49    36.0
5    26    45    44.0    28.0    42    33    43    45.0
6    29    46    42.0    30.0    45    15    29    NaN
7    28    23    26.0    28.0    29    15    18    32.0

2) pandas处理空值操作

  • isnull()
  • notnull()
  • dropna(): 过滤丢失数据 可以选择过滤的是行还是列(默认为行):axis中0表示行,1表示的列
  • fillna(): 填充丢失数据
#创建DataFrame,给其中某些元素赋值为nan
df.notnull().all(axis=1)
df[df.notnull().all(axis=1)]


0    1    2    3    4    5    6    7
0    29    36    36.0    30.0    43    17    20    33.0
3    10    34    45.0    12.0    29    26    10    15.0
5    26    45    44.0    28.0    42    33    43    45.0
7    28    23    26.0    28.0    29    15    18    32.0

3 填充函数 Series/DataFrame

fillna():value和method参数

可以选择前向填充还是后向填充, method 控制填充的方式 bfill ffill

df.fillna(method='ffill', axis=0)

    0    1    2    3    4    5    6    7
0    29    36    36.0    30.0    43    17    20    33.0
1    43    21    49.0    30.0    30    33    49    10.0
2    11    44    49.0    45.0    20    10    29    35.0
3    10    34    45.0    12.0    29    26    10    15.0
4    11    11    45.0    15.0    48    26    49    36.0
5    26    45    44.0    28.0    42    33    43    45.0
6    29    46    42.0    30.0    45    15    29    45.0
7    28    23    26.0    28.0    29    15    18    32.0

 

# 检查哪些列存在空值 并对检查出的空值进行覆盖
df.isnull().any(axis=0)
df.fillna(method='ffill', axis=0, inplace=True)
df

0    1    2    3    4    5    6    7
0    29    36    36.0    30.0    43    17    20    33.0
1    43    21    49.0    30.0    30    33    49    10.0
2    11    44    49.0    45.0    20    10    29    35.0
3    10    34    45.0    12.0    29    26    10    15.0
4    11    11    45.0    15.0    48    26    49    36.0
5    26    45    44.0    28.0    42    33    43    45.0
6    29    46    42.0    30.0    45    15    29    45.0
7    28    23    26.0    28.0    29    15    18    32.0

八 Pands的高级操作

1、删除重复元素(数据清洗的一种方式)

使用duplicated()函数检测重复的行,返回元素为布尔类型的Series对象,每个元素对应一行,如果该行不是第一次出现,则元素为True

- keep参数:指定保留哪一重复的行数据
  • 创建具有重复元素行的DataFrame
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
#创建一个df
df = DataFrame(data=np.random.randint(0, 100, size=(8,4)))
df

#手动将df的某几行设置成相同的内容
df.iloc[2] = [66,66,66,66]
df.iloc[4] = [66,66,66,66]
df.iloc[7] = [66,66,66,66]

# 使用duplicated查看所有重复元素行
df.duplicated(keep='first')
0    False
1    False
2    False
3    False
4     True
5    False
6    False
7     True
dtype: bool

# 删除重复元素的行
# 发生重复的行索引
index = df.loc[df.duplicated(keep='last')].index
df.drop(labels=index, axis=0)

使用drop_duplicates()函数删除重复的行

  • drop_duplicates(keep='first/last'/False)
df.drop_duplicates(keep="last")

    0    1    2    3
0    65    41    7    32
1    15    17    13    38
3    95    96    53    79
5    54    81    49    78
6    13    58    0    26
7    66    66    66    66

 2. 映射

1) replace()函数:替换元素

使用replace()函数,对values进行映射操作

Series替换操作

  • 单值替换
    • 普通替换
    • 字典替换(推荐)
  • 多值替换
    • 列表替换
    • 字典替换(推荐)
  • 参数
    • to_replace:被替换的元素

DataFrame替换操作

  • 单值替换
    • 普通替换: 替换所有符合要求的元素:to_replace=15,value='e'
    • 按列指定单值替换: to_replace={列标签:替换值} value='value'
  • 多值替换
    • 列表替换: to_replace=[] value=[]

字典替换(推荐) to_replace={to_replace:value,to_replace:value}

# 单值替换
df.replace(to_replace=66, value=666)
    0    1    2    3
0    65    41    7    32
1    15    17    13    38
2    66    66    66    66
3    95    96    53    79
4    66    66    66    66
5    54    81    49    78
6    13    58    0    26
7    66    66    66    66
# 多值替换
df.replace(to_replace=[66, 25], value=[63, 2255])

    0    1    2    3
0    65    41    7    32
1    15    17    13    38
2    63    63    63    63
3    95    96    53    79
4    63    63    63    63
5    54    81    49    78
6    13    58    0    26
7    63    63    63    63
# key列索引,value要替换的值
df.replace(to_replace={2:66}, value=666)

    0    1    2    3
0    65    41    7    32
1    15    17    13    38
2    66    66    666    66
3    95    96    53    79
4    66    66    666    66
5    54    81    49    78
6    13    58    0    26
7    66    66    666    66

注意:DataFrame中,无法使用method和limit参数

2) map()函数:新建一列 , map函数并不是df的方法,而是series的方法

  • map()可以映射新一列数据
  • map()中可以使用lambd表达式
  • map()中可以使用方法,可以是自定义的方法

    eg:map({to_replace:value})

  • 注意 map()中不能使用sum之类的函数,for循环
# 新增一列:给df中,添加一列,该列的值为中文名对应的英文名
dic = {
    'name':['jay', 'tom', 'jay'],
    'salary':[10000,15000,10000]
}
df = DataFrame(data=dic)
df

    name     salary
0    jay    10000
1    tom    15000
2    jay    10000
# 定制一个映射关系表
dic = {
    'jay':'周杰伦',
    'tom':'张三'
}
df['c_name'] = df['name'].map(dic)
df

     name    salary    c_name
0    jay    10000    周杰伦
1    tom    15000    张三
2    jay    10000    周杰伦

#### map当做一种运算工具,至于执行何种运算,是由map函数的参数决定的(参数:lambda,函数)
- 使用自定义函数

#超过10000部分的钱缴纳50%的税
def after_sal(s):
    if s < 10000:
        return s
    else:
        return s-(s-10000)*0.5
df['after_sal']=df['salary'].map(after_sal)
df

    name salary    c_name    after_sal
0    jay    10000    周杰伦    10000.0
1    tom    15000    张三      12500.0
2    jay    10000    周杰伦    10000.0

- 使用lambda表达式

df['after_sal']=df['salary'].map(lambda s:s-(s-10000)*0.5)

注意:并不是任何形式的函数都可以作为map的参数。只有当一个函数具有一个参数且有返回值,那么该函数才可以作为map的参数

3. 使用聚合操作对数据异常值检测和过滤

使用df.std()函数可以求得DataFrame对象每一列的标准差

# 创建一个1000行3列的df 范围(0-1),求其每一列的标准差
df = DataFrame(data=np.random.random(size=(1000,3)), columns=['A','B','C'])

    A              B                        C
0    0.623677    0.296882    0.180331
1    0.151164    0.838745    0.074804
2    0.810686    0.278847    0.632431
3    0.949126    0.836832    0.363521
.............................

# 对df应用筛选条件,去除标准差太大的数据:假设过滤条件为 C列数据大于两倍的C列标准差

value_std = df['C'].std() * 2
df['C'] <= value_std 
df.loc[df['C'] <= value_std ]

4. 排序

使用.take()函数排序

- take()函数接受一个索引列表,用数字表示,使得df根据列表中索引的顺序进行排序
- eg:df.take([1,3,4,2,5])

可以借助np.random.permutation()函数随机排序

# 对列进行乱序
df.take([2,1,0],axis=1)
     C                B                   A
0    0.227520    0.448755    0.946236
1    0.651939    0.880108    0.395235
2    0.917283    0.914232    0.584911
3    0.837992    0.267088    0.821250
4    0.489001    0.435002    0.901875
# np.random.permutation(x)可以生成x个从0-(x-1)的随机数列
random_df = df.take(np.random.permutation(1000), axis=0).take(np.random.permutation(3), axis=1)
random_df[0:100]

           C                  B          A
290    0.712080    0.287919    0.798695
188    0.148218    0.500367    0.334136
335    0.789687    0.518180    0.951512
617    0.196197    0.740249    0.065249
............................

# 随机抽样
# 当DataFrame规模足够大时,直接使用np.random.permutation(x)函数,就配合take()函数实现随机抽样

5. 数据分类处理【重点】

数据聚合是数据处理的最后一步,通常是要使每一个数组生成一个单一的数值。

数据分类处理:

  • 分组:先把数据分为几组
  • 用函数处理:为不同组的数据应用不同的函数以转换数据
  • 合并:把不同组得到的结果合并起来

数据分类处理的核心:

 - groupby()函数
 - groups属性查看分组情况
 - eg: df.groupby(by='item').groups

分组

df = DataFrame({'item':['Apple','Banana','Orange','Banana','Orange','Apple'],
                'price':[4,3,3,2.5,4,2],
               'color':['red','yellow','yellow','green','green','green'],
               'weight':[12,20,50,30,20,44]})
df
# 使用groupby实现分组
df.groupby(by='item', axis=0).groups
{'Apple': Int64Index([0, 5], dtype='int64'),
 'Banana': Int64Index([1, 3], dtype='int64'),
 'Orange': Int64Index([2, 4], dtype='int64')}

# 计算出苹果的平均价格
df.groupby(by='item',axis=0).mean()['price'][0]
# 先取出列再运算节省计算成本
df.groupby(by='item')['price'].mean()[0]

# 按颜色查看各种颜色的水果的平均价格
color_price = df.groupby(by='color')['price'].mean()
dic = color_price.to_dict()
df['color_mean_price'] = df['color'].map(dic)
df

    item    price    color    weight    mean_price    color_mean_price
0    Apple    4.0    red    12    3.00    4.000000
1    Banana    3.0    yellow    20    2.75    3.000000
2    Orange    3.0    yellow    50    3.50    3.000000
3    Banana    2.5    green    30    2.75    2.833333
4    Orange    4.0    green    20    3.50    2.833333
5    Apple    2.0    green    44    3.00    2.833333

# 汇总:将各种颜色水果的平均价格和df进行汇总
mean_price = df.groupby(by='item')['price'].mean()
dic = mean_price.to_dict()
df['mean_price'] = df['item'].map(dic)
df


item    price    color    weight    mean_price
0    Apple    4.0    red    12    3.00
1    Banana    3.0    yellow    20    2.75
2    Orange    3.0    yellow    50    3.50
3    Banana    2.5    green    30    2.75
4    Orange    4.0    green    20    3.50
5    Apple    2.0    green    44    3.00

6 高级数据聚合

使用groupby分组后,也可以使用transform和apply提供自定义函数实现更多的运算

  • df.groupby('item')['price'].sum() <==> df.groupby('item')['price'].apply(sum)
  • transform和apply都会进行运算,在transform或者apply中传入函数即可
  • transform和apply也可以传入一个lambda表达式
#使用apply函数求出水果的平均价格
def fun(s):
    sum = 0
    for i in s:
        sum+=s
    return sum/s.size

df.groupby(by='item')['price'].apply(fun)

0    4.0
1    3.0
2    3.0
3    2.5
4    4.0
5    2.0
Name: price, dtype: float64

#使用transform函数求出水果的平均价格
df.groupby(by='item')['price'].transform(fun)
df


item    price    color    weight    mean_price    color_mean_price
0    Apple    4.0    red    12    3.00    4.000000
1    Banana    3.0    yellow    20    2.75    3.000000
2    Orange    3.0    yellow    50    3.50    3.000000
3    Banana    2.5    green    30    2.75    2.833333
4    Orange    4.0    green    20    3.50    2.833333
5    Apple    2.0    green    44    3.00    2.833333

 

posted on 2019-05-06 10:39  cs_1993  阅读(402)  评论(0编辑  收藏  举报