Pandas [CHI]
pandas¶
- pandas这个名字源于 panel data( 面板数据),以及 Python data analysis。
- Pandas以NumPy为基础,让以NumPy为中心的应用变得更加简单。
- 提供了大量适用于金融数据的高性能时间序列工具。 作者在设计该包时就计划将其做成一款适用于金融数据分析的工具。
内容¶
- Pandas的数据结构介绍
- Seires
- DataFrame
- 基本功能
- 汇总和计算描述统计
- 处理缺失数据
- 其他
- 通常在调用Pandas之前做如下的引入约定:
import pandas as pd
from pandas import Series, DataFrame
import numpy as np
from numpy.random import randn
import os
import matplotlib.pyplot as plt
from myfunctions import *
np.random.seed(12345)
plt.rc('figure', figsize=(10, 6))
np.set_printoptions(precision=4)
介绍Pandas数据结构¶
要使用pandas,首先得熟悉两个主要的数据结构:Series 和 DataFrame。
Series¶
一种类似于一维数组的对象,数据(values)及其标签(index)组成,和numpy array的差别是具有index
obj = Series([100, 99, 100, 60])
obj
0 100 1 99 2 100 3 60 dtype: int64
obj.values
array([100, 99, 100, 60], dtype=int64)
obj.index
RangeIndex(start=0, stop=4, step=1)
- 在构建Series时,通过"index="参数指定索引,不指定就默认为$0,1,2,\cdots$
obj2 = Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c'])
obj2
d 4 b 7 a -5 c 3 dtype: int64
- 用索引引用数据,
obj2['a']
-5
和NumPy一样选取数据,对数据进行计算。只不过Series每个数据都有一个关键字索引。
obj2['d'] = 6
obj2[['c', 'a', 'd']]
c 3 a -5 d 6 dtype: int64
- 用条件判断,布尔值索引
obj2[obj2 > 0]
d 6 b 7 c 3 dtype: int64
- 可以将Series看成一个有序字典,定义了索引值到数据值的一个映射。
obj2
d 6 b 7 a -5 c 3 dtype: int64
- 注意使用in的结果
'b' in obj2.index
True
6 in obj2.values
True
- 如果数据被存在字典中,我们可以直接通过该字典来创建Series
sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}
obj3 = Series(sdata)
obj3
Ohio 35000 Oregon 16000 Texas 71000 Utah 5000 dtype: int64
- 可以通过index选择数据,即可以指定Series的index,只提取该index中存在的索引及其对应值。
states = ['California', 'Ohio', 'Oregon', 'Texas']
obj4 = Series(sdata, index=states)
obj4
California NaN Ohio 35000.0 Oregon 16000.0 Texas 71000.0 dtype: float64
- 但Clifornia在字典sdata中没有,这时在pandas中产生一个缺失值。
- 通过isnull方法判断是否有缺失值
pd.isnull(obj4)
California True Ohio False Oregon False Texas False dtype: bool
- Series一个最重要的功能是:它在算术运算中会自动对齐不同索引的数据。
obj3
Ohio 35000 Oregon 16000 Texas 71000 Utah 5000 dtype: int64
obj4
California NaN Ohio 35000.0 Oregon 16000.0 Texas 71000.0 dtype: float64
obj3 + obj4
California NaN Ohio 70000.0 Oregon 32000.0 Texas 142000.0 Utah NaN dtype: float64
- 可以通过赋值的方式修改索引。
obj
0 100 1 99 2 100 3 60 dtype: int64
obj.index = ['Tom', 'Steve', 'Jeff', 'Ryan']
obj
Tom 100 Steve 99 Jeff 100 Ryan 60 dtype: int64
DataFrame¶
- DataFrame是表格型的数据结构,其含有一组有序的列,每列可以是不同的类型(数值,字符串,布尔等)
- DataFrame既有行索引也有列索引,它可以被看做由Series组成的字典(共用同一个索引)
- 最常见的构建DataFrame的方法
- NumPy数组组成的字典。
- 二维ndarray生成DataFrame
data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'],
'year': [2000, 2001, 2002, 2001, 2002],
'pop': [1.5, 1.7, 3.6, 2.4, 2.9]}
frame = DataFrame(data)
frame
pop | state | year | |
---|---|---|---|
0 | 1.5 | Ohio | 2000 |
1 | 1.7 | Ohio | 2001 |
2 | 3.6 | Ohio | 2002 |
3 | 2.4 | Nevada | 2001 |
4 | 2.9 | Nevada | 2002 |
我们可以指定列的顺序。
DataFrame(data, columns=['year', 'state', 'pop'])
year | state | pop | |
---|---|---|---|
0 | 2000 | Ohio | 1.5 |
1 | 2001 | Ohio | 1.7 |
2 | 2002 | Ohio | 3.6 |
3 | 2001 | Nevada | 2.4 |
4 | 2002 | Nevada | 2.9 |
如果传入的数据不存在,就会产生NA值:
frame2 = DataFrame(data, columns=['year', 'state', 'pop', 'debt'],
index=['one', 'two', 'three', 'four', 'five'])
frame2
year | state | pop | debt | |
---|---|---|---|---|
one | 2000 | Ohio | 1.5 | NaN |
two | 2001 | Ohio | 1.7 | NaN |
three | 2002 | Ohio | 3.6 | NaN |
four | 2001 | Nevada | 2.4 | NaN |
five | 2002 | Nevada | 2.9 | NaN |
通过引用一个列,可以获得一个Series,下面是两种引用方法
frame2['state']
one Ohio two Ohio three Ohio four Nevada five Nevada Name: state, dtype: object
frame2.year
one 2000 two 2001 three 2002 four 2001 five 2002 Name: year, dtype: int64
- 行的引用,ix方法
frame2.ix['three']
C:\Anaconda\envs\py3\lib\site-packages\ipykernel_launcher.py:1: DeprecationWarning: .ix is deprecated. Please use .loc for label based indexing or .iloc for positional indexing See the documentation here: http://pandas.pydata.org/pandas-docs/stable/indexing.html#ix-indexer-is-deprecated """Entry point for launching an IPython kernel.
year 2002 state Ohio pop 3.6 debt NaN Name: three, dtype: object
#frame2.loc['three']
frame2.iloc[2]
year 2002 state Ohio pop 3.6 debt NaN Name: three, dtype: object
给DataFrame的列赋值,
将标量赋值给列中所有单元
frame2['debt'] = 16.5
frame2
year | state | pop | debt | |
---|---|---|---|---|
one | 2000 | Ohio | 1.5 | 16.5 |
two | 2001 | Ohio | 1.7 | 16.5 |
three | 2002 | Ohio | 3.6 | 16.5 |
four | 2001 | Nevada | 2.4 | 16.5 |
five | 2002 | Nevada | 2.9 | 16.5 |
- 用list或数组赋值,列的长度必须和DataFrame长度匹配
frame2['debt'] = np.arange(5.)
frame2
year | state | pop | debt | |
---|---|---|---|---|
one | 2000 | Ohio | 1.5 | 0.0 |
two | 2001 | Ohio | 1.7 | 1.0 |
three | 2002 | Ohio | 3.6 | 2.0 |
four | 2001 | Nevada | 2.4 | 3.0 |
five | 2002 | Nevada | 2.9 | 4.0 |
- 如果赋值的是一个Series,就会精确匹配索引,空的地方或用缺失值补上。
val = Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five'])
frame2['debt'] = val
frame2
year | state | pop | debt | |
---|---|---|---|---|
one | 2000 | Ohio | 1.5 | NaN |
two | 2001 | Ohio | 1.7 | -1.2 |
three | 2002 | Ohio | 3.6 | NaN |
four | 2001 | Nevada | 2.4 | -1.5 |
five | 2002 | Nevada | 2.9 | -1.7 |
- 为不存在的列赋值
frame2['eastern'] = frame2.state == 'Ohio'
frame2
year | state | pop | debt | eastern | |
---|---|---|---|---|---|
one | 2000 | Ohio | 1.5 | NaN | True |
two | 2001 | Ohio | 1.7 | -1.2 | True |
three | 2002 | Ohio | 3.6 | NaN | True |
four | 2001 | Nevada | 2.4 | -1.5 | False |
five | 2002 | Nevada | 2.9 | -1.7 | False |
- 关键字 del用于删除列。
del frame2['eastern']
frame2.columns
Index(['year', 'state', 'pop', 'debt'], dtype='object')
- 将嵌套的字典传给DataFrame时,外层字典的键为列,内层为行索引。
pop = {'Nevada': {2001: 2.4, 2002: 2.9},
'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}
frame3 = DataFrame(pop)
frame3
Nevada | Ohio | |
---|---|---|
2000 | NaN | 1.5 |
2001 | 2.4 | 1.7 |
2002 | 2.9 | 3.6 |
- 行和列都有关键字索引,也可以进行转置
frame3.T
2000 | 2001 | 2002 | |
---|---|---|---|
Nevada | NaN | 2.4 | 2.9 |
Ohio | 1.5 | 1.7 | 3.6 |
Frame 的值 是ndarray
frame3.values
array([[nan, 1.5], [2.4, 1.7], [2.9, 3.6]])
frame2.values
array([[2000, 'Ohio', 1.5, nan], [2001, 'Ohio', 1.7, -1.2], [2002, 'Ohio', 3.6, nan], [2001, 'Nevada', 2.4, -1.5], [2002, 'Nevada', 2.9, -1.7]], dtype=object)
- 也可以直接用二维ndarray生成DataFrame
frame4=DataFrame(np.array([[0, 1.5],
[ 2.4, 1.7],
[ 2.9, 3.6]]),index=['2001','2002','2003'],columns=['Nevada','Ohio'])
frame4
Nevada | Ohio | |
---|---|---|
2001 | 0.0 | 1.5 |
2002 | 2.4 | 1.7 |
2003 | 2.9 | 3.6 |
- 最常用的方法是从文件中读入
stockinfo=pd.read_excel("E:\\我的坚果云\\2017datafin\\A股基本资料.xlsx")
x=stockinfo['主营产品名称']
a=x[1]
b=stockinfo['主营产品类型']
b[2]
'物业出租和管理、系统集成服务、血液系统用制剂、原料药、植物类中药制剂'
stockinfo.columns
Index(['证券代码', '证券简称', '上市地点', '股票简称', '股票英文简称', '上市日期', '公司属性', '成立日期', '主营产品名称', '主营产品类型', '员工总数\r\n[交易日期] 2011-12-31', '员工总数\r\n[交易日期] 2012-12-31', '员工总数\r\n[交易日期] 2013-12-31', '员工总数\r\n[交易日期] 2014-12-31', '员工总数\r\n[交易日期] 2015-12-31', '员工总数\r\n[交易日期] 2016-12-31', '省份', '城市', '公司电话', '公司传真', '公司电子邮件地址', '公司网站', '公司发行证券一览', '董事长\r\n[交易日期] 最新', '公司独立董事(现任)', '公司独立董事(历任)', '总经理\r\n[交易日期] 最新', '资产评估机构', '法律顾问', '审计机构'], dtype='object')
stockinfo.tail(1)
证券代码 | 证券简称 | 上市地点 | 股票简称 | 股票英文简称 | 上市日期 | 公司属性 | 成立日期 | 主营产品名称 | 主营产品类型 | ... | 公司电子邮件地址 | 公司网站 | 公司发行证券一览 | 董事长 [交易日期] 最新 | 公司独立董事(现任) | 公司独立董事(历任) | 总经理 [交易日期] 最新 | 资产评估机构 | 法律顾问 | 审计机构 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
3364 | 数据来源:Wind资讯 | NaN | NaN | NaN | NaN | NaT | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1 rows × 30 columns
目前国内共三个商品期货交易所、一个金融期货交易所,四个交易所的品种分别为:
中国金融交易所:沪深300股指期货(沪深两家证券交易所精选300只股票,加权计算得出的指数,反映A股市场整体走势的指数)
上海期货交易所:铜、铝、橡胶、燃料油、锌、黄金、螺纹钢、线材、铅
大连商品交易所:大豆、豆粕、豆油、玉米、塑料(聚乙烯)、棕榈油、PVC(聚氯乙烯)、焦炭
郑州商品交易所:小麦、棉花、白糖、PTA(精对苯二甲酸)、菜籽油、早籼稻
- 商品现货交易所,渤海商品交易所, 上市品种,原油、焦炭、动力煤、螺纹钢、热卷板、PTA、白糖、聚酯切片、电解镍。
finfutureinfo=pd.read_excel("E:\\我的坚果云\\2017datafin\\中金所品种.xlsx")
finfutureinfo.loc[20]
证券代码 IH1710.CFE 证券简称 IH1710 期货简称 IH1710 期货代码 IH1710 交易所简称 中国金融期货交易所 涨跌幅限制 10 交易保证金 15 开始交易日 2017-08-21 00:00:00 最后交易日 2017-10-20 00:00:00 最后交割日 2017-10-20 00:00:00 交割月份 201710 交易品种 上证50股指期货 交易单位 1张 合约乘数 300 报价单位 张 最小变动价位 0.2指数点 最初交易保证金 最低交易保证金:合约价值的15% 最初交易保证金.1 最低交易保证金:合约价值的15% Name: 20, dtype: object
commodityinfo=pd.read_excel("E:\\我的坚果云\\2017datafin\\大连商品品种.xlsx")
commodityinfo.loc[1]
证券代码 V1711.DCE 证券简称 PVC1711 期货简称 PVC1711 期货代码 V1711 交易所简称 大连商品交易所 涨跌幅限制 5 交易保证金 7 开始交易日 2016-11-15 00:00:00 最后交易日 2017-11-14 00:00:00 最后交割日 2017-11-17 00:00:00 交割月份 201711 交易品种 聚氯乙烯 交易单位 5吨 合约乘数 5 报价单位 吨 最小变动价位 5人民币元/吨 最初交易保证金 最低交易保证金:合约价值的7% 最初交易保证金.1 最低交易保证金:合约价值的7% Name: 1, dtype: object
commodityinfo.tail(2)
证券代码 | 证券简称 | 期货简称 | 期货代码 | 交易所简称 | 涨跌幅限制 | 交易保证金 | 开始交易日 | 最后交易日 | 最后交割日 | 交割月份 | 交易品种 | 交易单位 | 合约乘数 | 报价单位 | 最小变动价位 | 最初交易保证金 | 最初交易保证金.1 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
165 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaT | NaT | NaT | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
166 | 数据来源:Wind资讯 | NaN | NaN | NaN | NaN | NaN | NaN | NaT | NaT | NaT | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
基本功能¶
我们介绍操作Series和DataFrame中数据的基本手段。
舍弃某些数据¶
- 可以通过drop方法删指定索引上的值,即删掉一行。
obj = Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e'])
obj.drop(['d', 'c'])
a 0.0 b 1.0 e 4.0 dtype: float64
- 选项 axis=1,则删列.
data = DataFrame(np.arange(16).reshape((4, 4)),
index=['Ohio', 'Colorado', 'Utah', 'New York'],
columns=['one', 'two', 'three', 'four'])
data.drop(['two', 'four'], axis=1)
one | three | |
---|---|---|
Ohio | 0 | 2 |
Colorado | 4 | 6 |
Utah | 8 | 10 |
New York | 12 | 14 |
data
one | two | three | four | |
---|---|---|---|---|
Ohio | 0 | 1 | 2 | 3 |
Colorado | 4 | 5 | 6 | 7 |
Utah | 8 | 9 | 10 | 11 |
New York | 12 | 13 | 14 | 15 |
- 请大家删掉上面wind数据中空白行、以及"wind 数据来源”行
commodityinfo.shape
commodityinfo.drop()
索引、选取和过滤 ( Indexing, selection, and filtering)¶
- Series可以通过索引,整数,布尔型进行选择。
- DataFrame的索引能获得一或多列。
- 如果需要对行进行选择,需要用到 .ix方法。
- 回顾一下Series
#用一个或多个关键字索引
obj = Series(np.arange(4.), index=['a', 'b', 'c', 'd'])
print(obj['b']) # index
obj[['b', 'a', 'd']]
1.0
b 1.0 a 0.0 d 3.0 dtype: float64
#通过一个整数或整数list索引
print(obj[1])
obj[[1, 3]]
1.0
b 1.0 d 3.0 dtype: float64
#用逻辑值索引
obj[obj < 2]
a 0.0 b 1.0 dtype: float64
- 对DataFrame的索引
data = DataFrame(np.arange(16).reshape((4, 4)),
index=['Ohio', 'Colorado', 'Utah', 'New York'],
columns=['one', 'two', 'three', 'four'])
data
one | two | three | four | |
---|---|---|---|---|
Ohio | 0 | 1 | 2 | 3 |
Colorado | 4 | 5 | 6 | 7 |
Utah | 8 | 9 | 10 | 11 |
New York | 12 | 13 | 14 | 15 |
- 对列索引,[[]]
print(data)
data[['three', 'one']]
one two three four Ohio 0 1 2 3 Colorado 4 5 6 7 Utah 8 9 10 11 New York 12 13 14 15
three | one | |
---|---|---|
Ohio | 2 | 0 |
Colorado | 6 | 4 |
Utah | 10 | 8 |
New York | 14 | 12 |
- 对行索引
print(data)
data[:2] # 切片适用
one two three four Ohio 0 1 2 3 Colorado 4 5 6 7 Utah 8 9 10 11 New York 12 13 14 15
one | two | three | four | |
---|---|---|---|---|
Ohio | 0 | 1 | 2 | 3 |
Colorado | 4 | 5 | 6 | 7 |
#利用逻辑值索引行
print(data)
data[(data['three'] > 5) & (data['four']>7)]
one two three four Ohio 0 1 2 3 Colorado 4 5 6 7 Utah 8 9 10 11 New York 12 13 14 15
one | two | three | four | |
---|---|---|---|---|
Utah | 8 | 9 | 10 | 11 |
New York | 12 | 13 | 14 | 15 |
- 利用逻辑值索引
data < 5
one | two | three | four | |
---|---|---|---|---|
Ohio | True | True | True | True |
Colorado | True | False | False | False |
Utah | False | False | False | False |
New York | False | False | False | False |
data[data < 5]
one | two | three | four | |
---|---|---|---|---|
Ohio | 0.0 | 1.0 | 2.0 | 3.0 |
Colorado | 4.0 | NaN | NaN | NaN |
Utah | NaN | NaN | NaN | NaN |
New York | NaN | NaN | NaN | NaN |
data[data < 5] = 0
data
one | two | three | four | |
---|---|---|---|---|
Ohio | 0 | 0 | 0 | 0 |
Colorado | 0 | 5 | 6 | 7 |
Utah | 8 | 9 | 10 | 11 |
New York | 12 | 13 | 14 | 15 |
- 使用.iloc,.loc索引,指定行
#只指定一个整数,索引一列
data.iloc[2]
one 8 two 9 three 10 four 11 Name: Utah, dtype: int32
同时指定行列
#data1=data.ix[['Colorado', 'Utah'], ['two', 'three']]
data2=data.ix[['Colorado', 'Utah'], [3, 0, 1]]
data3=data.ix[data.three > 5, :3]
side_by_side(data,data2,data3)
one | two | three | four | |
---|---|---|---|---|
Ohio | 0 | 0 | 0 | 0 |
Colorado | 0 | 5 | 6 | 7 |
Utah | 8 | 9 | 10 | 11 |
New York | 12 | 13 | 14 | 15 |
four | one | two | |
---|---|---|---|
Colorado | 7 | 0 | 5 |
Utah | 11 | 8 | 9 |
one | two | three | |
---|---|---|---|
Colorado | 0 | 5 | 6 |
Utah | 8 | 9 | 10 |
New York | 12 | 13 | 14 |
#新版本中的更新
#data.ix[['Colorado', 'Utah'], [3, 0, 1]]
data.loc[['Colorado', 'Utah'], data.columns[[3, 0, 1]]]
four | one | two | |
---|---|---|---|
Colorado | 7 | 0 | 5 |
Utah | 11 | 8 | 9 |
算术运算和数据对齐¶
- 在进行计算时会将索引对齐,是pandas最重要的功能。
- 将两个不同索引的对象相加时,结果的索引为两对象索引的并,相同索引的值相加,不同索引处为缺失值。
- DataFrame, 同时在行和列上对齐。
s1 = Series([7.3, -2.5, 3.4, 1.5], index=['a', 'c', 'd', 'e'])
s2 = Series([-2.1, 3.6, -1.5, 4, 3.1], index=['a', 'c', 'e', 'f', 'g'])
s1 + s2
a 5.2 c 1.1 d NaN e 0.0 f NaN g NaN dtype: float64
df1 = DataFrame(np.arange(9.).reshape((3, 3)), columns=list('bcd'),
index=['Ohio', 'Texas', 'Colorado'])
df2 = DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'),
index=['Utah', 'Ohio', 'Texas', 'Oregon'])
side_by_side(df1,df2,df1 + df2)
b | c | d | |
---|---|---|---|
Ohio | 0.0 | 1.0 | 2.0 |
Texas | 3.0 | 4.0 | 5.0 |
Colorado | 6.0 | 7.0 | 8.0 |
b | d | e | |
---|---|---|---|
Utah | 0.0 | 1.0 | 2.0 |
Ohio | 3.0 | 4.0 | 5.0 |
Texas | 6.0 | 7.0 | 8.0 |
Oregon | 9.0 | 10.0 | 11.0 |
b | c | d | e | |
---|---|---|---|---|
Colorado | NaN | NaN | NaN | NaN |
Ohio | 3.0 | NaN | 6.0 | NaN |
Oregon | NaN | NaN | NaN | NaN |
Texas | 9.0 | NaN | 12.0 | NaN |
Utah | NaN | NaN | NaN | NaN |
处理运算中的缺失值¶
可以通过 fill_value在NaN的地方填充一个值, 算术方法分别为 add,sub,div,mul
df1 = DataFrame(np.arange(12.).reshape((3, 4)), columns=list('abcd'))
df2 = DataFrame(np.arange(20.).reshape((4, 5)), columns=list('abcde'))
#dfadd=df1+df2
dfaddfill0=df1.add(df2, fill_value=0)
side_by_side(df1,df2,dfaddfill0)
a | b | c | d | |
---|---|---|---|---|
0 | 0.0 | 1.0 | 2.0 | 3.0 |
1 | 4.0 | 5.0 | 6.0 | 7.0 |
2 | 8.0 | 9.0 | 10.0 | 11.0 |
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 0.0 | 1.0 | 2.0 | 3.0 | 4.0 |
1 | 5.0 | 6.0 | 7.0 | 8.0 | 9.0 |
2 | 10.0 | 11.0 | 12.0 | 13.0 | 14.0 |
3 | 15.0 | 16.0 | 17.0 | 18.0 | 19.0 |
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 0.0 | 2.0 | 4.0 | 6.0 | 4.0 |
1 | 9.0 | 11.0 | 13.0 | 15.0 | 9.0 |
2 | 18.0 | 20.0 | 22.0 | 24.0 | 14.0 |
3 | 15.0 | 16.0 | 17.0 | 18.0 | 19.0 |
DataFrame 和 Series 之间的运算¶
- 当一个向量减去一个标量时,向量中的每个值都会减去该值。
arr = np.arange(12.).reshape((3, 4))
#print(arr)
#arr - arr[0]
arr
array([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.]])
arr - arr[0]
array([[0., 0., 0., 0.], [4., 4., 4., 4.], [8., 8., 8., 8.]])
- 减去一个Sereis,其每行都要做相同的操作
frame = DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'),
index=['Utah', 'Ohio', 'Texas', 'Oregon'])
series = frame.iloc[0]
fsubr=frame - series
side_by_side(frame,fsubr)
b | d | e | |
---|---|---|---|
Utah | 0.0 | 1.0 | 2.0 |
Ohio | 3.0 | 4.0 | 5.0 |
Texas | 6.0 | 7.0 | 8.0 |
Oregon | 9.0 | 10.0 | 11.0 |
b | d | e | |
---|---|---|---|
Utah | 0.0 | 0.0 | 0.0 |
Ohio | 3.0 | 3.0 | 3.0 |
Texas | 6.0 | 6.0 | 6.0 |
Oregon | 9.0 | 9.0 | 9.0 |
- Pandas和一般数组不同的是,它还要进行列索引的匹配。
- 如果有不匹配的,还要生成新的列,并用缺失值NaN代替。这种操作被称为广播。
series2 = Series(range(3), index=['b', 'e', 'f'])
frame + series2
b | d | e | f | |
---|---|---|---|---|
Utah | 0.0 | NaN | 3.0 | NaN |
Ohio | 3.0 | NaN | 6.0 | NaN |
Texas | 6.0 | NaN | 9.0 | NaN |
Oregon | 9.0 | NaN | 12.0 | NaN |
- 一般的广播都是按行进行,如果希望在列上进行,则要进行设定, axis=0,此处传入的是进行匹配的轴。
series3 = frame['d']
fsubc=frame.sub(series3, axis=0)
side_by_side(frame,fsubc)
b | d | e | |
---|---|---|---|
Utah | 0.0 | 1.0 | 2.0 |
Ohio | 3.0 | 4.0 | 5.0 |
Texas | 6.0 | 7.0 | 8.0 |
Oregon | 9.0 | 10.0 | 11.0 |
b | d | e | |
---|---|---|---|
Utah | -1.0 | 0.0 | 1.0 |
Ohio | -1.0 | 0.0 | 1.0 |
Texas | -1.0 | 0.0 | 1.0 |
Oregon | -1.0 | 0.0 | 1.0 |
函数应用和映射¶
NumPy的函数也可以操作到pandas对象
frame = DataFrame(np.random.randn(4, 3), columns=list('bde'),
index=['Utah', 'Ohio', 'Texas', 'Oregon'])
fabs=np.abs(frame)
side_by_side(frame,fabs)
b | d | e | |
---|---|---|---|
Utah | -0.204708 | 0.478943 | -0.519439 |
Ohio | -0.555730 | 1.965781 | 1.393406 |
Texas | 0.092908 | 0.281746 | 0.769023 |
Oregon | 1.246435 | 1.007189 | -1.296221 |
b | d | e | |
---|---|---|---|
Utah | 0.204708 | 0.478943 | 0.519439 |
Ohio | 0.555730 | 1.965781 | 1.393406 |
Texas | 0.092908 | 0.281746 | 0.769023 |
Oregon | 1.246435 | 1.007189 | 1.296221 |
- 将函数应用到各列或者各行计算得到一个一维数组,可以用apply方法,这样方法也是R中的重要方法。
frame
b | d | e | |
---|---|---|---|
Utah | -0.204708 | 0.478943 | -0.519439 |
Ohio | -0.555730 | 1.965781 | 1.393406 |
Texas | 0.092908 | 0.281746 | 0.769023 |
Oregon | 1.246435 | 1.007189 | -1.296221 |
f = lambda x: x.max() - x.min()
frame.apply(f)
b 1.802165 d 1.684034 e 2.689627 dtype: float64
# 将函数应用到列
frame.apply(f, axis=1)
Utah 0.998382 Ohio 2.521511 Texas 0.676115 Oregon 2.542656 dtype: float64
- 若函数只有一个返回值,apply之后得到一个Series。
- 若有多个返回值,则得到DateFrame
def f(x):
return Series([x.min(), x.max()], index=['min', 'max'])
frame.apply(f)
b | d | e | |
---|---|---|---|
min | -0.555730 | 0.281746 | -1.296221 |
max | 1.246435 | 1.965781 | 1.393406 |
- 元素级(即每个数值)的Python函数在DataFrame也可以用,使用applymap即可
- 如下的例子实现每个元素的输出特定的格式
format = lambda x: '%.2f' % x
frame.applymap(format)
b | d | e | |
---|---|---|---|
Utah | -0.20 | 0.48 | -0.52 |
Ohio | -0.56 | 1.97 | 1.39 |
Texas | 0.09 | 0.28 | 0.77 |
Oregon | 1.25 | 1.01 | -1.30 |
- 对Sereis,相应的方法为map
frame['e'].map(format)
Utah -0.52 Ohio 1.39 Texas 0.77 Oregon -1.30 Name: e, dtype: object
练习:
- 如何识别空行和空列?
- 如何统计每列变量的统计特征?
序¶
- 按照索引关键字进行排序,使用sort_index方法,
- 对DataFrame,默认对行排,如果对列索引排,需要指明 axis=1,
- 选项 ascending =False 表示降序。
- 如果需要对Series的值排序,sort_values。缺失值会放到末尾。
- 对DataFrame的值进行排序,传递给选项by列名称即可。
#按照索引关键字进行排序,使用sort_index方法,
obj = Series(range(4), index=['d', 'a', 'b', 'c'])
obj.sort_index()
a 1 b 2 c 3 d 0 dtype: int64
#对DataFrame,默认对行排
frame = DataFrame(np.arange(8).reshape((2, 4)), index=['three', 'one'],
columns=['d', 'a', 'b', 'c'])
frame.sort_index()
d | a | b | c | |
---|---|---|---|---|
one | 4 | 5 | 6 | 7 |
three | 0 | 1 | 2 | 3 |
#,如果对列索引排,需要指明 axis=1,
frame.sort_index(axis=1)
a | b | c | d | |
---|---|---|---|---|
three | 1 | 2 | 3 | 0 |
one | 5 | 6 | 7 | 4 |
frame.sort_index(axis=1, ascending=False)
d | c | b | a | |
---|---|---|---|---|
three | 0 | 3 | 2 | 1 |
one | 4 | 7 | 6 | 5 |
#如果需要对Series的值排序,则用order方法。缺失值会放到末尾。
obj = Series([4, 7, -3, 2])
obj.sort_values()
2 -3 3 2 0 4 1 7 dtype: int64
obj = Series([4, np.nan, 7, np.nan, -3, 2])
obj.sort_values()
4 -3.0 5 2.0 0 4.0 2 7.0 1 NaN 3 NaN dtype: float64
# 对DataFrame的值进行排序,传递给选项by列名称即可。
frame = DataFrame({'b': [4, 7, -3, 2], 'a': [0, 1, 0, 1]})
sortbyb=frame.sort_values(by='b')
sortbyab=frame.sort_values(by=['a', 'b'])
side_by_side(frame,sortbyb,sortbyab)
b | a | |
---|---|---|
0 | 4 | 0 |
1 | 7 | 1 |
2 | -3 | 0 |
3 | 2 | 1 |
b | a | |
---|---|---|
2 | -3 | 0 |
3 | 2 | 1 |
0 | 4 | 0 |
1 | 7 | 1 |
b | a | |
---|---|---|
2 | -3 | 0 |
0 | 4 | 0 |
3 | 2 | 1 |
1 | 7 | 1 |
- rank方法给出Series各元素的序号
- 对DataFrame,可以逐行或列给出序号
obj = Series([7, -5, 7, 4, 2, 0, 4])
obj.rank()
0 6.5 1 1.0 2 6.5 3 4.5 4 3.0 5 2.0 6 4.5 dtype: float64
obj.rank(ascending=False, method='max')
0 2.0 1 7.0 2 2.0 3 4.0 4 5.0 5 6.0 6 4.0 dtype: float64
frame = DataFrame({'b': [4.3, 7, -3, 2], 'a': [0, 1, 0, 1],
'c': [-2, 5, 8, -2.5]})
side_by_side(frame,frame.rank())
b | a | c | |
---|---|---|---|
0 | 4.3 | 0 | -2.0 |
1 | 7.0 | 1 | 5.0 |
2 | -3.0 | 0 | 8.0 |
3 | 2.0 | 1 | -2.5 |
b | a | c | |
---|---|---|---|
0 | 3.0 | 1.5 | 2.0 |
1 | 4.0 | 3.5 | 3.0 |
2 | 1.0 | 1.5 | 4.0 |
3 | 2.0 | 3.5 | 1.0 |
frame.rank(axis=1)
b | a | c | |
---|---|---|---|
0 | 3.0 | 2.0 | 1.0 |
1 | 3.0 | 1.0 | 2.0 |
2 | 1.0 | 2.0 | 3.0 |
3 | 3.0 | 2.0 | 1.0 |
有重复的索引¶
索引值可以是不唯一的
obj = Series(range(5), index=['a', 'a', 'b', 'b', 'c'])
obj
a 0 a 1 b 2 b 3 c 4 dtype: int64
obj['a']
a 0 a 1 dtype: int64
df = DataFrame(np.random.randn(4, 3), index=['a', 'a', 'b', 'b'])
df
0 | 1 | 2 | |
---|---|---|---|
a | 0.274992 | 0.228913 | 1.352917 |
a | 0.886429 | -2.001637 | -0.371843 |
b | 1.669025 | -0.438570 | -0.539741 |
b | 0.476985 | 3.248944 | -1.021228 |
df.loc['b']
0 | 1 | 2 | |
---|---|---|---|
b | 1.669025 | -0.438570 | -0.539741 |
b | 0.476985 | 3.248944 | -1.021228 |
汇总和描述性统计量的计算¶
下面介绍一些汇总和描述性统计量的计算。
包括,count, describe, min,max, argmin, argmax, idxmin, idxmax, quantile, sum,mean, median, mad,var,std, skew,kurt,cumsum, cummin, cummax, cumprod, diff, pct_change等
df = DataFrame([[1.4, np.nan], [7.1, -4.5],
[np.nan, np.nan], [0.75, -1.3]],
index=['a', 'b', 'c', 'd'],
columns=['one', 'two'])
df.sum()
one 9.25 two -5.80 dtype: float64
df.sum(axis=1)
#缺失值处理方法?
a 1.40 b 2.60 c 0.00 d -0.55 dtype: float64
df.sum(axis=1, skipna=False)
a NaN b 2.60 c NaN d -0.55 dtype: float64
df['three']=1
df
one | two | three | |
---|---|---|---|
a | 1.40 | NaN | 1 |
b | 7.10 | -4.5 | 1 |
c | NaN | NaN | 1 |
d | 0.75 | -1.3 | 1 |
df.idxmax()
# first occurrence
one b two d three a dtype: object
res1=df.cumsum(axis=1)
side_by_side(df,res1)
one | two | three | |
---|---|---|---|
a | 1.40 | NaN | 1 |
b | 7.10 | -4.5 | 1 |
c | NaN | NaN | 1 |
d | 0.75 | -1.3 | 1 |
one | two | three | |
---|---|---|---|
a | 1.40 | NaN | 2.40 |
b | 7.10 | 2.60 | 3.60 |
c | NaN | NaN | 1.00 |
d | 0.75 | -0.55 | 0.45 |
obj = Series(['a', 'b', 'b', 'b'] * 4)
obj.describe()
count 16 unique 2 top b freq 12 dtype: object
唯一集合,频数等¶
obj = Series(['c', 'a', 'd', 'a', 'a', 'b', 'b', 'c', 'c'])
uniques = obj.unique()
uniques
array(['c', 'a', 'd', 'b'], dtype=object)
#计算频数
obj.value_counts()
a 3 c 3 b 2 d 1 dtype: int64
# 判断包含关系
mask = obj.isin(['b', 'c'])
mask
0 True 1 False 2 False 3 False 4 False 5 True 6 True 7 True 8 True dtype: bool
#利用布尔索引,取出相应数据
obj[mask]
0 c 5 b 6 b 7 c 8 c dtype: object
data = DataFrame({'Qu1': [1, 3, 4, 3, 4],
'Qu2': [2, 3, 1, 2, 3],
'Qu3': [1, 5, 2, 4,5]})
# 计算各个数出现的频数,按列
result = data.apply(pd.value_counts,axis=1)
side_by_side(data,result)
Qu1 | Qu2 | Qu3 | |
---|---|---|---|
0 | 1 | 2 | 1 |
1 | 3 | 3 | 5 |
2 | 4 | 1 | 2 |
3 | 3 | 2 | 4 |
4 | 4 | 3 | 5 |
1 | 2 | 3 | 4 | 5 | |
---|---|---|---|---|---|
0 | 2.0 | 1.0 | NaN | NaN | NaN |
1 | NaN | NaN | 2.0 | NaN | 1.0 |
2 | 1.0 | 1.0 | NaN | 1.0 | NaN |
3 | NaN | 1.0 | 1.0 | 1.0 | NaN |
4 | NaN | NaN | 1.0 | 1.0 | 1.0 |
处理缺失值¶
string_data = Series(['aardvark', 'artichoke', np.nan, 'avocado'])
string_data
0 aardvark 1 artichoke 2 NaN 3 avocado dtype: object
string_data.isnull()
0 False 1 False 2 True 3 False dtype: bool
数据选择,滤掉一些缺失值¶
- 函数 data.dropna(),data.notnull()
from numpy import nan as NA
data = Series([1, NA, 3.5, NA, 7])
data.dropna()
0 1.0 2 3.5 4 7.0 dtype: float64
data[data.notnull()]
0 1.0 2 3.5 4 7.0 dtype: float64
# DataFrame
data = DataFrame([[1., 6.5, 3.], [1., NA, NA],
[NA, NA, NA], [NA, 6.5, 3.]])
data
0 | 1 | 2 | |
---|---|---|---|
0 | 1.0 | 6.5 | 3.0 |
1 | 1.0 | NaN | NaN |
2 | NaN | NaN | NaN |
3 | NaN | 6.5 | 3.0 |
cleaned = data.dropna()
cleaned
0 | 1 | 2 | |
---|---|---|---|
0 | 1.0 | 6.5 | 3.0 |
data.dropna?
# 其它参数选项
res1=data.dropna(axis=0,how='all')
side_by_side(data,res1)
0 | 1 | 2 | |
---|---|---|---|
0 | 1.0 | 6.5 | 3.0 |
1 | 1.0 | NaN | NaN |
2 | NaN | NaN | NaN |
3 | NaN | 6.5 | 3.0 |
0 | 1 | 2 | |
---|---|---|---|
0 | 1.0 | 6.5 | 3.0 |
1 | 1.0 | NaN | NaN |
3 | NaN | 6.5 | 3.0 |
填补缺失值¶
df.fillna(0)
one | two | three | |
---|---|---|---|
a | 1.40 | 0.0 | 1 |
b | 7.10 | -4.5 | 1 |
c | 0.00 | 0.0 | 1 |
d | 0.75 | -1.3 | 1 |
- 传入字典实现 不同列填补不同数据
res2=df.fillna({"one": 0.5, "two": -1},axis=0)
side_by_side(df,res2)
one | two | three | |
---|---|---|---|
a | 1.40 | NaN | 1 |
b | 7.10 | -4.5 | 1 |
c | NaN | NaN | 1 |
d | 0.75 | -1.3 | 1 |
one | two | three | |
---|---|---|---|
a | 1.40 | -1.0 | 1 |
b | 7.10 | -4.5 | 1 |
c | 0.50 | -1.0 | 1 |
d | 0.75 | -1.3 | 1 |
分层索引¶
data = Series(np.random.randn(10),
index=[['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'd', 'd'],
[1, 2, 3, 1, 2, 3, 1, 2, 2, 3]])
data
a 1 -0.577087 2 0.124121 3 0.302614 b 1 0.523772 2 0.000940 3 1.343810 c 1 -0.713544 2 -0.831154 d 2 -2.370232 3 -1.860761 dtype: float64
data.index
MultiIndex(levels=[['a', 'b', 'c', 'd'], [1, 2, 3]], labels=[[0, 0, 0, 1, 1, 1, 2, 2, 3, 3], [0, 1, 2, 0, 1, 2, 0, 1, 1, 2]])
data['b']
1 0.523772 2 0.000940 3 1.343810 dtype: float64
data['b':'c']
b 1 0.523772 2 0.000940 3 1.343810 c 1 -0.713544 2 -0.831154 dtype: float64
data.loc[['b', 'd']]
b 1 0.523772 2 0.000940 3 1.343810 d 2 -2.370232 3 -1.860761 dtype: float64
内层引用
data[:, 2]
a 0.124121 b 0.000940 c -0.831154 d -2.370232 dtype: float64
使用 DataFrame的列作为索引使用¶
frame = DataFrame({'a': range(7), 'b': range(7, 0, -1),
'c': ['one', 'one', 'one', 'two', 'two', 'two', 'two'],
'd': [0, 1, 2, 0, 1, 2, 3],
"e":["四川"]*5+["北京"]*2})
frame
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 0 | 7 | one | 0 | 四川 |
1 | 1 | 6 | one | 1 | 四川 |
2 | 2 | 5 | one | 2 | 四川 |
3 | 3 | 4 | two | 0 | 四川 |
4 | 4 | 3 | two | 1 | 四川 |
5 | 5 | 2 | two | 2 | 北京 |
6 | 6 | 1 | two | 3 | 北京 |
frame2 = frame.set_index(['c', 'd'])
frame2
a | b | e | ||
---|---|---|---|---|
c | d | |||
one | 0 | 0 | 7 | 四川 |
1 | 1 | 6 | 四川 | |
2 | 2 | 5 | 四川 | |
two | 0 | 3 | 4 | 四川 |
1 | 4 | 3 | 四川 | |
2 | 5 | 2 | 北京 | |
3 | 6 | 1 | 北京 |
frame.set_index(['c', 'd'], drop=False)
a | b | c | d | e | ||
---|---|---|---|---|---|---|
c | d | |||||
one | 0 | 0 | 7 | one | 0 | 四川 |
1 | 1 | 6 | one | 1 | 四川 | |
2 | 2 | 5 | one | 2 | 四川 | |
two | 0 | 3 | 4 | two | 0 | 四川 |
1 | 4 | 3 | two | 1 | 四川 | |
2 | 5 | 2 | two | 2 | 北京 | |
3 | 6 | 1 | two | 3 | 北京 |
frame2.reset_index()
数据合并¶
可以根据关键字进行合并,非常灵活。
df1 = DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
'data1': range(7)})
df2 = DataFrame({'key': ['a', 'b', 'b'],
'data2': range(3)})
side_by_side(df1,df2)
key | data1 | |
---|---|---|
0 | b | 0 |
1 | b | 1 |
2 | a | 2 |
3 | c | 3 |
4 | a | 4 |
5 | a | 5 |
6 | b | 6 |
key | data2 | |
---|---|---|
0 | a | 0 |
1 | b | 1 |
2 | b | 2 |
pd.merge(df1, df2) # 共同的关键字,inner
key | data1 | data2 | |
---|---|---|---|
0 | b | 0 | 1 |
1 | b | 0 | 2 |
2 | b | 1 | 1 |
3 | b | 1 | 2 |
4 | b | 6 | 1 |
5 | b | 6 | 2 |
6 | a | 2 | 0 |
7 | a | 4 | 0 |
8 | a | 5 | 0 |