pandas是一种Python数据分析的利器,是一个开源的数据分析包, 最初是应用于金融数据分析工具而开发出来的,因此pandas为时间 序列分析提供了很好的支持。pandas是PyData项目的一部分。

安装过程详见: 官方安装文档。

Python版本要求:2.7、3.4、3.5、3.。

依赖Python库:setuptools、NumPy、python-dateutil、pytz。

安装方式:

Python的Anaconda发行版,已经安装好pandas库,不需要另外安装。

使用Anaconda界面安装,选择对应的pandas进行勾选安装即可。

使用Anaconda命令安装:conda install pandas。

使用PyPi安装命令安装:pip install pandas

引入约定:from pandas import Series, DataFrame或import pandas as pd

pandas基本数据结构

pandas中主要有两种数据结构,分别是:Series和DataFrame。

Series:一种类似于一维数组的对象,是由一组数据(各种NumPy数 据类型)以及一组与之相关的数据标签(即索引)组成。仅由一组数据也 可产生简单的Series对象。注意:Series中的索引值是可以重复的。

DataFrame:一个表格型的数据结构,包含有一组有序的列,每列 可以是不同的值类型(数值、字符串、布尔型等),DataFrame即有行 索引也有列索引,可以被看做是由Series组成的字典。

Series数据结构

通过一维数组创建Series

panda series和df区别_数组

panda series和df区别_数据_02

通过字典创建Series

panda series和df区别_sqlalchemy_03

panda series和df区别_数组_04

panda series和df区别_panda series和df区别_05

import pandas as pd
import numpy as np
'''
    使用列表创建
'''
ser01 = pd.Series([1,2,3,4])

'''
    使用数组创建
'''
ser02 = pd.Series(np.random.randint(1,9,5))

'''
    使用字典创建Series
'''
dic = {
    'a':1,
    'b':2,
    'c':3
}
ser03 = pd.Series(dic)

print(ser03.index)
print(ser03.values)
print(ser03.dtype)

'''
    设置index
'''
# 修改index的值
ser02.index = list('abcde')
print(ser02)
#创建时 制定 index
ser05 = pd.Series(np.random.randint(1,9,5),index = ['a','b','c','d','e'])
print(ser05)

View Code

Series常见属性

import pandas as pd
import numpy as np
'''
    常见属性
'''
ser02 = pd.Series(np.random.randint(1,9,5),index = ['a','b','c','d','e'])

ser02.name = '帅哥'
ser02.index.name = '编号'
# print('数据标题:{}'.format(ser02.name))
# print('数据行索引的标题:{}'.format(ser02.index.name))
# print('行轴标签列表:{}'.format(ser02.axes))
# print('对象的数据类型:{}'.format(ser02.dtype))
# print('对象是否为空:{}'.format(ser02.empty))
# print('Series对象的行索引:{}'.format(ser02.index))
# print('Series对象底层数据的维度数:{}'.format(ser02.ndim))
# print('Series对象的元素个数:{}'.format(ser02.size))
# print('Series对象作为ndarray数组返回:',ser02.values,sep='\n')
# print('返回Series对象的前n行:',ser02.head(3),sep='\n')
# print('返回Series对象的后n行:',ser02.tail(3),sep='\n')

Series值得获取

Series值的获取主要有两种方式:

通过方括号+索引的方式读取对应索引的数据,有可能返回多条数据。

通过方括号+下标值的方式读取对应下标值的数据,下标值的取值范围为: [0,len(Series.values));另外下标值也可以是负数,表示从右往左获取数据。

Series切片

Series获取多个值的方式类似NumPy中的ndarray的切片操作,通 过方括号+下标值/索引值+冒号(:)的形式来截取series对象中的一部 分数。

import pandas as pd
import numpy as np
np.random.seed(28)
ser02 = pd.Series(np.random.randint(1,9,5),index = ['a','b','c','d','e'])
# 通过索引获取
print(ser02['a'])

#通过数字下标获取
print(ser02[0])
print(ser02[-1])

# 获取多个元素
print(ser02[['a','c']])

# 切片
print(ser02['a':'c'])
print(type(ser02['a':'c']))

# 具有相同索引, 不能通过下标获取。
ser = pd.Series(np.random.randint(1,9,5),index = ['a','b','b','d','e'])
print(ser['b'])
# print(ser[0]) #会报错

series的运算

NumPy中的数组运算,在Series中都保留了,均可以使用,并且 Series进行数组运算的时候,索引与值之间的映射关系不会发生改变。

注意:其实在操作Series的时候,基本上可以把Series看成NumPy 中的ndarray数组来进行操作。ndarray数组的绝大多数操作都可以 应用到Series上。

import pandas as pd
import numpy as np
ser01 = pd.Series(np.random.randint(1,5,5))
# 与标量进行运算
# print(ser01+10)
# print(ser01-10)
# print(ser01*10)
# print(ser01/10)
# print(ser01**2)

# series 与 series  的运算
print(ser01)
ser02 = pd.Series(np.random.randint(1,5,5))
print(ser02)

# print(ser01+ser02)
# print(ser01-ser02)
# print(ser01*ser02)
# print(ser01/ser02)
# print(ser01**ser02)

# 直接使用numpy的通用函数
# print(np.log(ser01))
# print(np.exp(ser01))
# print(ser01[ser01<4])
# print(ser01<4)

Series自动对齐

 当多个series对象之间进行运算的时候,如果不同series之间具有不 同的索引值,那么运算会自动对齐相同索引值的数据,如果某个 series没有某个索引值,那么最终结果会赋值为NaN。

import pandas as pd
import numpy as np
ser01 = pd.Series(np.random.randint(1,5,5),index = list('abcde'))
print(ser01)
ser02 = pd.Series(np.random.randint(1,5,5),index = list('abmne'))
print(ser02)

mask = ser01+ser02   # 对于无法通过下标对应的数据 被重新赋值为NaN
print(mask)

Series缺失值检测

pandas中的isnull和notnull两个函数可以用于在Series中检测缺失 值,这两个函数的返回时一个布尔类型的Series。

import pandas as pd
import numpy as np
ser01 = pd.Series(np.random.randint(1,5,5),index = list('abcde'))
ser01['b'] = np.NaN
ser01['e'] = np.NaN
print(ser01)
print(ser01.isnull() )  # 返回一个bool series
print(ser01[~ser01.isnull()] )  # 过滤缺失值
print(ser01.notnull())
print(ser01[ser01.notnull()] )  # 过滤缺失值

# 结合numpy 函数过滤NaN数据
print(np.isnan(ser01))
print(ser01[~np.isnan(ser01)] )

DataFrame数据帧

panda series和df区别_panda series和df区别_06

通过二维数组创建Dataframe

 

panda series和df区别_panda series和df区别_07

通过字典的方式创建Dataframe

panda series和df区别_数组_08

索引对象与DataFrame数据获取

索引对象

不管是Series还是DataFrame对象,都有索引对象。 索引对象负责管理轴标签和其它元数据(eg:轴名称等等)。

通过索引可以从Series、DataFrame中获取值或者对某个索引值进行重新赋值。

Series或者DataFrame的自动对齐功能是通过索引实现的。

import pandas as pd
import numpy as np

'''
    通过列表创建
'''
li = [[1,2,3,4],[5,6,7,8]]
df01 = pd.DataFrame(li)
# print(df01.shape) #查看数据形状
# print(df01.ndim)
# print(df01.dtypes) #查看数据类型
# print(df01.index) #查看行索引
# print(df01.columns) #查看列索引
# print('返回数据的ndarray形式:',df01.values,sep='\n')

'''
    通过series创建
'''
ser01 = pd.Series([1,2,3,4])
ser02 = pd.Series([1,2,3,4])
df02 = pd.DataFrame([ser01,ser02])

'''
    数组创建
'''
arr = np.random.randint(1,9,(3,3))
df03 = pd.DataFrame(arr)

'''
    字典创建
'''
dic = {
    'name':['joe','anne','yilianna'],   #  key 就是 列索引
    'age':[18,19,20],
    'class':1                          # 要求字典的value必须是长度相等的序列或是一个标量
}
df04 = pd.DataFrame(dic,index=['一班','二班','三班']) #自定义索引值
print(df04)
# print('行索引:{}'.format(df04.index))
# print('列索引:{}'.format(df04.columns))
# print('数据:',df04.values,sep='\n')

'''
    重置索引
'''
# df04.index = list('abc')
# df04.index.name = 'index' #行索引的标题
# df04.columns.name = 'info'#列索引的标题
# print(df04)

#删除索引
# print(df04.reset_index(drop=True))
# print(df04)

'''
    设置某一列为行索引
'''
df04 = df04.set_index('name')
print(df04.axes) #查看行和列的索引标签
print(df04)

'''
    重置列索引
'''
df04.columns = list('AB')
print(df04)

DataFrame数据获取

 可以直接通过列索引获取指定列的数据, eg: df[column_name],取某个值:df[column_name,index_name]

如果需要获取指定行的数据的话,需要通过ix方法来获取对应行索引 的行数据,eg: df.ix[index_name]、loc、iloc。取某个值:df.ix[index_name,column_name]

import pandas as pd
import numpy as np

'''
    通过列表创建
'''
li = [[1,2,3,4],[5,6,7,8]]
df = pd.DataFrame(li)
df.index.name = 'index_name'
df.columns.name = 'columns_name'

print(df)
#获取列
# print(df[1])

#列切片
# df.columns = list('abcd')
# print(df[df.columns[0:2]]) #只能用下标切片

#获取行
# print(df.loc[1])
# print(df.iloc[1])
# print(df.ix[1])

#行切片
# print(df.loc[0:2])
print(df.loc[0:1,0:1]) #左闭右闭

#获取某个值
print(df.loc[0,1])
print(df.loc[1,0])

DataFrame数据的增删改查

import pandas as pd
import numpy as np

'''
    列操作  查
'''
dic = {
    'name':['joe','anne','yilianna'],   #  key 就是 列索引
    'age':[18,19,20],
    'class':1                          # 整列数据会被标量填充
}
df03 = pd.DataFrame(dic)

print(df03['name'] )  # 返回一个series
# 获取多列数据
print(df03[['name','age']])   # 当获取多列数据的时候返回DataFrame

'''
    增
'''
df03['address'] = ['usa','uk','chn']   # 添加不存在的列索引
print(df03)

'''
    删
'''
df03.pop('address')   # 返回被删除的内容

# del(df03['address'])  # del 删除

'''
    改
'''
df03['class'] = [3,4,5]


'''
    行操作  查
'''
print(df03.loc[0])

# 获取多行数据
print(df03.loc[[0,2]])

# 选择某行某列
print(df03.loc[0,'name'])
print(df03.loc[[0,2],'name'])
print(df03.loc[[0,2],['name','age']])

# 切片
print(df03.loc[1:,'class':'name'])

df03.index = ['a','b','c']
print(df03.iloc[0] )  # 可以使用数字索引获取

print(df03.iloc[[0,1],[0,1]])

'''
    增
'''
df03.loc['d'] = [16,6,'ronaldo']    # 指定一个不存在的行索引  对应上每一列数据
print(df03)

'''
    删
'''
df03 = df03.drop('d')

'''
    改
'''
df03.loc['c'] = [18,9,'messi']

pandas基本功能

数据文件读取/存储

通过pandas提供的read_xxx相关的函数可以读取文件中的数据,并 形成DataFrame,常用的数据读取方法为:read_csv,主要可以读取 文本类型的数据。

 读/写数据库

import pandas as pd
import numpy as np
import sqlalchemy
from sqlalchemy import create_engine
from faker import Factory
import random

engine = create_engine('mysql+pymysql://user:password@ip:port/database_name?charset=utf8')

columns_name = ['name','age','sex','phone_number']
fake = Factory().create('ZH_cn')
sex = [random.choice(['男','女']) for k in range(5)]
name = [fake.name_male() if i == '男' else fake.name_female() for i in sex]
age = [random.choice([21,19,22,18,20]) for e in range(5)]
phone_number = [fake.phone_number() for j in range(5)]

data = np.array([name,age,sex,phone_number]).T
df = pd.DataFrame(data,columns=columns_name)
table_name = 'test_datas'

'''
name : string
    表名
con : sqlalchemy.engine.Engine or sqlite3.Connection
    一个SQLAlchemy的连接数据库的对象
schema : string, optional
    指定架构(如果数据库flavor支持此)。如果为None,请使用默认架构。
if_exists : {'fail', 'replace', 'append'}, default 'fail'
    如果表已存在,如何表现。
        fail:引发ValueError。
        replace:在插入新值之前删除表。
        append:将新值插入现有表。
index : bool, default True
    将DataFrame索引写为列。使用index_label作为表中的列名。
index_label : string or sequence, default None
    索引列的列标签。如果给出None(默认)且 index为True,则使用索引名称。如果DataFrame使用MultiIndex,则应该给出一个序列。
chunksize : int, optional
    行将一次批量写入此大小。默认情况下,所有行都将立即写入。
dtype : dict, optional
    指定列的数据类型。键应该是列名,值应该是SQLAlchemy类型或sqlite3传统模式的字符串。
'''
df.to_sql(table_name,engine,if_exists='append',index=False,
          dtype={
              'name':sqlalchemy.types.String(10),
              'age':sqlalchemy.types.Integer(),
              'sex':sqlalchemy.types.String(3),
              'phone_number':sqlalchemy.types.BigInteger()
          }
          )

print(pd.read_sql(table_name,engine))

读/写csv文件

import pandas as pd
import numpy as np
import sqlalchemy
from sqlalchemy import create_engine
from faker import Factory
import random


# '''
#     read_csv
# '''
# # 读取csv
# data = pd.read_csv('data1.csv',encoding = 'gbk')
#
# # 读取文本
# data2 = pd.read_csv('data1.txt',sep = '::',engine='python')
#
# # 读取Excel
# data3 = pd.read_excel('data1.xlsx')

'''
    保存文件
'''
fake = Factory().create('ZH_cn')

# columns_name = ['name','age','sex','phone_number']
# sex = [random.choice(['男','女']) for k in range(5)]
# name = [fake.name_male() if i == '男' else fake.name_female() for i in sex]
# age = [random.choice([21,19,22,18,20]) for e in range(5)]
# phone_number = [fake.phone_number() for j in range(5)]
#
# data = np.array([name,age,sex,phone_number]).T
# df = pd.DataFrame(data,columns=columns_name)
#
# # 保存文件为data.csv
# # df.index.name = 'name'  #与index=True时配合使用
# df.to_csv('data.csv',index = False,header = True) #header:是否把列名存入

#读取
date = ['a','b','c','d']

fb = pd.read_csv('data.csv',header = 0) #header:把第0行做为列名
# fb = pd.read_csv('data.csv',header = None,names=date)
fb = fb.set_index('name')
print(fb)

data2 = pd.read_csv('data1.txt',sep = '::',engine='python')
data = pd.read_csv('data1.csv',encoding = 'gbk')

读/写excel文件

pandas提供了 read_excel 函数来读取 "xls" "xlsx" 两种文件。

import pandas as pd
import numpy as np
import sqlalchemy
from sqlalchemy import create_engine
from faker import Factory
import random

fake = Factory().create('ZH_cn')

columns_name = ['name','age','sex','phone_number']
sex = [random.choice(['男','女']) for k in range(5)]
name = [fake.name_male() if i == '男' else fake.name_female() for i in sex]
age = [random.choice([21,19,22,18,20]) for e in range(5)]
phone_number = [fake.phone_number() for j in range(5)]

data = np.array([name,age,sex,phone_number]).T
# df = pd.DataFrame(data,columns=columns_name)

# 保存文件为data.xlsx
# df.index.name = 'name'  #与index=True时配合使用
# df.to_excel('data.xlsx',sheet_name='第一页',index = False,header = True) #header:是否把列名存入

# #读取
date = ['a','b','c','d']

fb = pd.read_excel('data.xlsx',header = 0) #header:把第0行做为列名
# fb = pd.read_excel('data.xlsx',header = None,names=date)
# fb = fb.set_index('name')
print(fb)

数据过滤获取

通过DataFrame的相关方式可以获取对应的列或者数据形成一个新 的DataFrame, 方便后续进行统计计算。

import pandas as pd
import numpy as np
import sqlalchemy
from sqlalchemy import create_engine
from faker import Factory
import random

fake = Factory().create('ZH_cn')

columns_name = ['name','age','sex','phone_number']
sex = [random.choice(['男','女']) for k in range(5)]
name = [fake.name_male() if i == '男' else fake.name_female() for i in sex]
age = [random.choice([21,19,22,18,20]) for e in range(5)]
phone_number = [fake.phone_number() for j in range(5)]

data = np.array([name,age,sex,phone_number]).T
df = pd.DataFrame(data,columns=columns_name)
print(df[['age','sex']])
print(df.loc[:,['age','sex']])
print(df.columns)
print(df[df.columns[1:3]])

缺省值NaN处理方法

对于DataFrame/Series中的NaN一般采取的方式为删除对应的列/ 行或者填充一个默认值。

panda series和df区别_panda series和df区别_09

import pandas as pd
import numpy as np
'''
    缺失值处理
'''
df01 = pd.DataFrame(np.random.randint(1,9,(4,4)),index = list('ABCD'),columns = list('abcd'))
df01.loc['B','c'] = np.NaN
df01.loc['C','b'] = np.NaN
# print(df01)
# print(df01['b'].isnull())

'''
    dropna
'''
# print(df01.dropna())  # 默认会删除带有 NaN 的行  只要包含一个就整行删除
# print(df01.dropna(axis = 1))    # 删除列中带有NaN的列

# 设置阀值
# df01 = df01.dropna(how = 'all')   # 只删除整行为  nan的行,默认值为any
# print(df01)

df01.loc['E'] = np.NaN
df01=df01.dropna(how='all')

'''
    fillna  处理
'''
# print(df01.fillna(0))  # 将所有的 nan 数据替换成了 0
# print(df01.fillna(method = 'ffill'))   # 根据前一个值进行替换
# print(df01.fillna(method = 'bfill'))   # 根据后一个值进行替换
print(df01.fillna({'b':100,'c':200}) )  # 根据列进行替换

df01.loc['A','a'] = 30
print(df01.replace({np.nan:'null',30:'haha'})) #替换多值

# df01.replace(np.nan,0,inplace=True)  #相当于df01 = df01.replace(np.nan,0)
print(df01)

常用的数学统计方法

panda series和df区别_数据_10

panda series和df区别_数据_11

import pandas as pd
import numpy as np
df01 = pd.DataFrame(np.random.randint(1,9,(4,4)),index = list('ABCD'),columns = list('abcd'))

'''
    count
'''
print(df01.count())
print(df01.count(axis = 1))

'''
    min
'''
print(df01.min())
print(df01.min(axis = 1))

'''
    idmin:返回最小值的下标
'''
print(df01.idxmin())


'''
    describe
'''
print(df01.describe())

print(df01.mad() ) # 平均绝对距离差

相关系数与协方差

相关系数:就是用X、Y的协方差除以X的标准差和Y的标准差。所以,相关系数也可以看成协方差:一种剔除 了两个变量量纲影响、标准化后的特殊协方差。 1.也可以反映两个变量变化时是同向还是反向,如果同向变化为正,反向变化为负 2.由于它是标准化后的协方差,因此更重的特性是,它消除了两个变量变化幅度的影响,而只是 单纯反应两个变量单位变化的相似程度。 注意: 相关系数不像协方差一样可以在+\infty 到-\infty 间变化,它只能在+1到-1之间变化 当相关系数为1的时候两者相识度最大,同向正相关 当相关系数为0的时候两者没有任何相似度,两个变量无关 当相关系数为-1的时候两者变化的反向相似度最大,完全反向负相关。

import pandas as pd

df01 = pd.DataFrame({
    'kill':[5,6,7,8],
    'duanwei':[4,2,3,1],
    'dgb':[1,3,8,9]})

print(df01['kill'].cov(df01['duanwei']))
print(df01['kill'].corr(df01['duanwei'],method='pearson'))
print(df01['kill'].corr(df01['duanwei'],method='kendall'))
print(df01['kill'].corr(df01['duanwei'],method='spearman'))
print(df01.corr())

唯一值,值计数以及成员资格

unique方法用于获取Series中的唯一值数组(去重数据后的数组)。

Value_counts方法返回一个包含值和该值出现次数的Series对象,次 序按照出现的频率由高到低排序.。

isin方法用于判断矢量化集合的成员资格,可用于选取Series中或者 DataFrame中列中数据的子集。

import pandas as pd

df01 = pd.DataFrame({
    'movie_name':list('abadcebe'),
    'rating':[4,5,3,5,3,4,3,5]
})

print(df01['movie_name'].unique())
result = df01['movie_name'].value_counts().head(3)
print(result)
print(df01['movie_name'].isin(result.index))  #成员判断
print(df01[df01['movie_name'].isin(result.index)])  #获取成员

层次索引

import pandas as pd
import numpy as np

ser01 = pd.Series([30,33,35,18,20,30],index = [
    [2017,2017,2017,2018,2018,2018],
    ['messi','cr7','nermaer','messi','cr7','nermaer']
])

# print(ser01)

# 获取数据
# print(ser01[2017,'messi'])
# print(ser01[2018]['cr7'])
# print(ser01[2018][['messi','cr7']])
# print(ser01[:,'nermaer'])
# print(ser01.swaplevel())  #交换索引级别
# print(ser01.swaplevel().sort_index()) #排序索引
# print(ser01.swapaxes())
# 转换成dataFrame
# ser01=ser01.unstack(level = 1) #把行索引分解成列索引
# print(ser01)
# print(ser01.stack()) ##把列索引合并成行索引
#
# print(ser01.stack().index)
#MultiIndex(levels=[[2017, 2018], ['cr7', 'messi', 'nermaer']],codes=[[0, 0, 0, 1, 1, 1], [0, 1, 2, 0, 1, 2]]) codes为levels的下标。

'''
    dataframe
'''
df01 = pd.DataFrame({
    'year':[2017,2017,2017,2018,2018,2018],
    'goal':[30,30,31,28,29,30],
    'zg':[15,16,13,18,13,14],
    'name':['messi','cr7','nermaer','messi','cr7','nermaer']
})

'''列 ——> 索引'''
# df01 = df01.set_index(['year','name'])
df01.set_index(['year','name'],inplace=True)


'''索引 ——> 列'''
#方法一
# print(np.array(list(df01.index)))
# year,name = zip(*list(df01.index)) #拆解多层索引
# df01['year'] = year

#方法二
# print(df01.reset_index(level=['year','name']))
# df01.reset_index(level=0, inplace=True)


#方法三
# print(df01.index.get_level_values('year'))
# df01['year'] = df01.index.get_level_values('year')

'''按层次索引进行统计'''
print(df01.sum(level='year'))
print(df01.mean(level='year'))
print(df01.sum(level='name'))
print(df01.mean(level='name'))

print(df01)

Pandas排序之sort_index与sort_values

sort_index 对行或列索引进行排序。

Series 的 sort_index(ascending=True) 方法可以对 index 进行排序 操作,ascending 参数用于控制升序或降序,默认为升序。

在 DataFrame 上,.sort_index(axis=0, ascending=True) 方法多了 一个轴向的选择参数。

sort_values对Series按值进行排序, 排序时,任何缺失值默认都会被放到Series的 末尾。

import pandas as pd
import numpy as np

'''
    sort_index
'''
ser01 = pd.Series([1,2,3,4,5],index = list('bdcae'))
# print(ser01)
# print(ser01.sort_index(ascending = True))      # 通过索引进行排序

df01 = pd.DataFrame(np.random.randint(1,9,(4,4)),index = list('BCDA'),columns = list('cadb'))
# print(df01)
#
# print(df01.sort_index(axis = 0))      # 默认对行索引进行排序
# print(df01.sort_index(axis = 1))

'''
   sort_values 
'''
ser02 = pd.Series([4,5,2,7,1],index = list('bdcae'))
print(ser02.sort_values(ascending = False))   # 倒序

df02 = pd.DataFrame(np.random.randint(1,9,(4,4)),index = list('BCDA'),columns = list('cadb'))

print(df01.sort_values(by = ['a','c'],ascending = False))
print(df01.sort_values(by = 'B',axis=1,ascending = False))

Pandas排名之rank

import pandas as pd
import numpy as np

'''
    rank
'''
# ser01 = pd.Series([4,5,2,2,1,2],index = list('bdcaef'))
# print(ser01.rank())   # 有重复的数字的排名则按它们的排名取均值:(2 + 3 + 4)/3 = 3
# print(ser01.rank(method = 'min'))  #默认 average
# print(ser01.rank(method = 'max'))
# print(ser01.rank(method = 'first'))

df = pd.DataFrame(np.random.randint(0,5,(4,4)))
print(df)
print(df.rank(method='min',ascending=False))    #按照列排名
print(df.rank(axis=1))    #按照行排名

Pandas之时间序列

在pandas中有一个非常常用的函数date_range,尤其是在处理时间 序列数据时,这个函数的作用就是产生一个DatetimeIndex,就是时 间序列数据的索引。

pandas.date_range(start=None, end=None, periods=None, freq=’D’, tz=None, normalize=False, name=None, closed=None, **kwargs)

参数:

 

start:string或datetime-like,默认值是None,表示日期的起点。

end:string或datetime-like,默认值是None,表示日期的终点。

periods:integer或None,默认值是None,表示你要从这个函数产生多少个日期索引值;如果是None的话,那么start和end 必须不能为None。

freq:string或DateOffset,默认值是’D’,表示以自然日为单位,这个参数用来指定计时单位,比如’5H’表示每隔5个 小时计算一次。

tz:string或None,表示时区,例如:’Asia/Hong_Kong’。

normalize:bool,默认值为False,如果为True的话,那么在产生时间索引值之前会先把start和end都转化为当日的午夜0点。

name:str,默认值为None,给返回的时间索引指定一个名字。

closed:string或者None,默认值为None,表示start和end这个区间端点是否包含在区间内,可以有三个值,’left’表示 左闭右开区间,’right’表示左开右闭区间,None表示两边都是闭区间。

import pandas as pd
import numpy as np

# pd.date_range(start = '20180701',end = '20180708')
# print(pd.date_range(start = '20180701',end = '20180708',freq = '2d'))
# print(pd.date_range(start = '20180701',periods = 5,freq = 'm'))
# print(pd.date_range(start = '20180701',end = '20180708',freq = '12h'))
# print(pd.date_range(start = '20180701',periods = 10,freq = '10min'))
print(pd.date_range(start = '20180701',periods = 10,freq = '10s'))

Pandas之表合并

merge:

pandas.merge 可根据一个或多个键将不同 DataFrame 中的行连接起来。 on=None 用于显示指定列名(键名),如果该列在两个对象上的列名不同,则可以通过 left_on=None, right_on=None 来分别指定。或者想直接使用行索引作为连接键的话,就将 left_index=False, right_index=False 设为 True。

how='inner' 参数指的是当左右两个对象中存在不重合的键时,取结果的方式:inner 代表交集;outer 代表并集;left 和 right 分别为取一边。

suffixes=('_x','_y') 指的是当左右对象中存在除连接键外的同名列时,结果集中的区分方式,可以各加一个小尾巴。

对于多对多连接,结果采用的是行的笛卡尔积。

concat:

pandas.concat 可以沿着一条轴将多个对象堆叠到一起 objs: series,dataframe或者是panel构成的序列lsit axis: 需要合并链接的轴,0是行,1是列。

join:连接的方式 inner,或者outer

import pandas as pd
import numpy as np

df01 = pd.DataFrame({
    'data1':[1,2,3,4,5],
    'key':list('abcde')
})
df02 = pd.DataFrame({
    'data2':[1,2,3,4,6],
    'key':list('abcdf')
})
# print(df01)
# print(df02)

'''
    merge
'''
print(pd.merge(df01,df02,on = 'key',how = 'inner'))  #取'key'的交集
print(pd.merge(df01,df02,on = 'key',how = 'outer'))  #取'并集'的交集
print(pd.merge(df01,df02,on = 'key',how = 'left'))
print(pd.merge(df01,df02,on = 'key',how = 'right'))

print(pd.merge(df01,df02,left_on = 'data1',right_on = 'data2',how = 'inner'))
print(pd.merge(df01,df02,left_on = 'data1',right_on = 'data2',how = 'outer',suffixes=('_1','_2')))
print(pd.merge(df01,df02,left_on = 'data1',right_on = 'data2',how = 'left'))
print(pd.merge(df01,df02,left_on = 'data1',right_on = 'data2',how = 'right'))

'''
    concat
'''

print(pd.concat([df01,df02],join = 'outer',sort=False) ) # 纵向合并
print(pd.concat([df01,df02],axis=1,join = 'outer',sort=False) ) # 纵向合并

Pandas分组与聚合操作

groupby 对DataFrame进行数据分组,传入列名列表或者Series序 列对象,返回生成一个GroupBy对象。它实际上还没有进行任何计算。

GroupBy对象是一个迭代对象,每次迭代结果是一个元组。

元组的第一个元素是该组的名称(就是groupby的列的元素名称)。 第二个元素是该组的具体信息,是一个数据框。

索引是以前的数据框的总索引。

import pandas as pd
import numpy as np

df01 = pd.DataFrame({
    'data1': [1, 2, 3, 4, 5],
    'data2': [10, 20, 30, 40, 50],
    'key1': list('aabba'),
    'sex': list('mwwmm')

})

print(df01)

#通过一列数据分组获取一列数据或两列数据
print(df01.groupby('key1'))
for i in df01.groupby('key1'):
    print(i[1])

print(df01.groupby('key1')['data1'].sum())
print(df01.groupby('key1')['data1'].mean())
print(df01.groupby('key1')['data1','data2'].max())

#通过两列数据分组获取一列数据或两列数据
for i in df01.groupby(['key1','sex']):
    print(i)
print(df01.groupby(['key1','sex'])['data1'].max())
print(df01.groupby(['key1','sex'])['data1'].max().unstack())
print(df01.groupby(['key1','sex'])['data1','data2'].max())

Pandas聚合之apply

apply 是 pandas 库的一个很重要的函数,多和 groupby 函数一起 用,也可以直接用于 DataFrame 和 Series 对象。主要用于数据聚合 运算,可以很方便的对分组进行现有的运算和自定义的运算。

panda series和df区别_sqlalchemy_12

import pandas as pd
import numpy as np

df01 = pd.DataFrame({
    'data1': [1, 2, 3, 4, 5],
    'data2': [10, 20, 30, 40, 50],
    'key1': list('aabba'),
    'sex': list('mwwmm')

})

print(df01)

'''
    apply
'''

# print(df01.groupby(['sex'])['data1'].apply(lambda x : x+10)) #做四则运算时则合并分组
# print(df01.groupby(['sex'])['data1'].apply(lambda x : x*10)) #做四则运算时则合并分组
# print(df01.groupby(['sex'])['data1'].apply(lambda x : x.sum())) #做统计是则分组运算
# print(df01.groupby(['sex'])['data1'].apply(lambda x : x.mean())) #做统计是则分组运算

np.random.seed(28)
df01 = pd.DataFrame(np.random.randint(1,9,(4,4)),index = list('ABCD'),columns = list('abcd'))
print(df01)

def f1(x):
    return x*10
print(df01.apply(f1))

def f2(x):
    if x['B'] == 5:
        x['B'] = 200
        print(x)
    return x
print(df01.apply(f2,axis=0)) #按列遍历,axis=1,则按行遍历
print(df01)

# 传递参数
def f3(x,y):
    if x['a'] == 200:
        x['a'] = str(x['a'])+ y
    return x
print(df01.apply(f3,args = ('hahha',),axis = 1))


'''
    练习一:
    要求:提取数据时间部分,返回对应的每行数据的年、月、日三列数据。效果如右下图所示。
'''
df02 = pd.DataFrame(np.random.randint(1,9,(4,4)),columns = list('ABCD'))
df02['E'] = pd.date_range(start = '20180702',periods = 4,freq = 'd')
print(df02)
import time
def get_time(x):
    # 转换时间元组
    tup_time = time.strptime(str(x),'%Y-%m-%d %H:%M:%S')
    return pd.Series([tup_time[0],tup_time.tm_mon,tup_time.tm_mday],index = list('YMD'))   # 使用Series返回 生成DataFrame
print(df02['E'].apply(get_time))

'''
    练习二

'''
df6 = pd.DataFrame({
    'name': ['joe', 'susan', 'anne', 'black', 'monika', 'ronaldo', 'leonarldo', 'tom', 'yilianna', 'bulanni'],
    'age': [19, 19, 18, 20, 20, 18, 19, 20, 18, 19],
    'sex': ['man', 'women', 'women', 'man', 'women', 'man', 'man', 'man', 'women', 'women'],
    'address': ['上海', '北京', '上海', '北京', '北京', '上海', '北京', '上海', '北京', '上海'],
    'money': [8000, 8500, 7000, 9000, 10000, 7500, 8800, 9300, 12000, 11000]
})
print(df6)

# 根据地区进行分组   查看平均年龄和工资
def f1(x):
    # print(x)
    return x.mean()

# print(df6.groupby('address')['age','money'].apply(f1))

# 根据年龄进行分组   查看平均工资
print(df6.groupby('age')['money'].apply(f1))

# 根据性别进行分组   查看平均工资
df6.groupby('sex')['money'].apply(f1)

# 先根据地区,然后在根据性别进行分组,查看各地区不同性别的平均工资
df6.groupby(['address','sex'])['money'].apply(f1)

'''agg:分组函数 可以同时应用多个聚合函数'''
#根据地区进行分组   查看工资的平均值
#最低值 最高值 和最高值与最低值的差
#agg()分组函数 可以同时应用多个聚合函数
def y(x):
    return x.max() - x.min()
print(df6.groupby(['address'])['money'].agg(['mean','max','min',('cha',y)]))


'''
    练习三
    根据性别进行成绩排序
    计算男女比例
    计算成绩分布,每个成绩段有多少人

'''
df = pd.DataFrame({'性别' : ['男', '女', '男', '女',
                              '男', '女', '男', '男'],
                   '成绩' : ['优秀', '优秀', '及格', '差',
                              '及格', '及格', '优秀', '差'],
                   '年龄' : [13,14,15,12,13,14,15,16]})
# 替换成绩字段
df = df.replace({'优秀':'A','及格':'B','差':'C'})
# print(df)

#根据性别进行成绩排序
def sotrs(x):
    print(x)
    return x.sort_values(by = '成绩')
print(df.groupby('性别').apply(sotrs))

# 计算男女比例
total = df['性别'].count()   # 获取总人数
sexs = df.groupby('性别')['性别'].count()
print(sexs)
print(sexs.apply(lambda x : str(x/total*100)+'%'))

# 计算成绩分布,每个成绩段有多少人
total = df['性别'].count()   # 获取总人数
score = df.groupby('成绩')['成绩'].count()
score.apply(lambda x : str(x/total*100)+'%')

Pandas之数据透视

数据透视表pivot_table,根据一个或多个键进行聚合,并根据行列上的 分组键将数据分配到各个矩形区域中。 DataFrame.pivot_table(data, values=None, index=None, columns=None, aggfunc=’mean’, fill_value=None, margins=False, dropna=True, margins_name=’All’)。

data: DataFrame对象。

values: 显示的列的名字,可以应用aggfunc中的函数。

index: 索引。

columns: 可选的, 通过额外的方法来分割你所关心的实际值,然而aggfunc被应用到values上, aggfunc默认的是mean。

import pandas as pd
import numpy as np
df = pd.DataFrame({
    'kill':[1,2,3,4,5],
    'address':['皮卡多','圣马丁','皮卡多','圣马丁','皮卡多'],
    'help':[3,4,2,5,2],
    'sex':['m','w','m','m','w']
})

# 通过index 进行 分组 查看 values 中的字段 的 aggfunc 值
print(df.pivot_table(values = ['kill','help'],index = ['address'],aggfunc = np.mean))
print(df.groupby('address')['kill','help'].apply(lambda x:x.mean()))
print(df.groupby('address')['kill','help'].mean())

print(df.pivot_table(values = ['kill','help'],index = ['address'],aggfunc = [np.mean,np.max,np.min]))

print(df.pivot_table(values = ['kill','help'],index = ['address'],columns = ['sex'],aggfunc = np.mean))

Pandas之去重

import pandas as pd
import numpy as np
arr = np.array(['b','a','a','a','d','a','b','c','b','b','a','a','b','b','f','e']).reshape(8,2)
df = pd.DataFrame(arr,columns=['a','b'])
print(pd.unique(df['a']))
print(df.drop_duplicates(subset='a')) #在 'a' 列上有重复的删除行
print(df.drop_duplicates(subset='a',keep='last')) #可以选定保留哪一行。
print(df.drop_duplicates(subset=['a','b'])) #在 'a' 列 和 'b' 列上每一行组成一个子集,若子集出现重复则删除行

pandas制图

import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
import pandas as pd

# 设置中文显示
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False

ser = pd.Series(np.random.randn(10).cumsum(),index = np.arange(0,100,10))
ser1 = pd.Series(np.random.randn(10).cumsum(),index = np.arange(0,100,10))
ser.plot()
ser1.plot(color = 'r')
plt.show()

# DataFrame
# df = pd.DataFrame(np.random.randint(1,9,(4,2)),index = ['1月','2月','3月','4月'],columns = ['鼓浪屿','张家界'])
# df.plot(kind = 'bar')
# plt.show()

pandas之加载网上数据

官网:https://pandas-datareader.readthedocs.io/en/latest/remote_data.html

准备工作:

pip install pandas==0.24.0
pip install pandas-datareader==0.6.0
pip install yfinance==0.1.43
把原fred.py文件到开头import中第一句是这个 from pandas.core.common import is_list_like 我们将这个句修改成:from pandas.api.types import is_list_like。

#定义所需要的数据
gafataDict={"谷歌":"GOOG","亚马逊":"AMZN","Facebook":"FB","苹果":"AAPL","阿里巴巴":"BABA","腾讯":"0700.hk"}
import pandas as pd
import numpy as np
from pandas_datareader import data, wb # 需要安装 pip install pandas_datareader
import datetime
import matplotlib.pyplot as plt
import matplotlib
import yfinance as yf
matplotlib.style.use('ggplot')
%matplotlib inline
%pylab inline
%config InlineBackend.figure_format = 'retina'
yf.pdr_override()  # 用来修复,必要
# 定义获取数据的时间段
start = datetime.datetime(2019, 1, 1)
end = datetime.date.today()

# 获取股票信息 ex: 中国石油
# 如果要看上证指数请参考换成600000.ss
# 如果要看深成指请换成000001.sz
cnpc = data.get_data_yahoo("601857.SS", start, end)


'''数据读取和输出pd.read_csv and to_csv'''
# cnpc.to_excel('cnpc_datas.xls',index = False,header = True)
# df = pd.read_excel('cnpc_datas.xls',header=0)

'''清洗数据'''
# 把所有数据都为0的列删除。
print(cnpc.shape)
print(cnpc.info())
abnormal_value = np.array([0 for i in range(cnpc.shape[0])])
for i in cnpc.columns:
#     print((~(cnpc[i]==abnormal_value)).astype(np.int).mean())
    if np.mean((cnpc[i]==abnormal_value).astype(np.int)) > 0.5:
        cnpc.drop(i,axis=1)

'''检查缺失值'''
# 下面把一些位置设置为np.nan,然后填充,没有实际意义,这里只是拿来练手。
cnpc.iloc[0,:] = np.nan
cnpc.iloc[[1,3],1] = np.nan
cnpc.iloc[2,2] = np.nan
cnpc.iloc[3,3] = np.nan
print(cnpc.info())
pd.isnull(cnpc).head() # or cnpc.isnull()
print(cnpc.isnull().values.any(axis=0)) # 统计nan值
print(cnpc.isnull().values.any(axis=1))
print(cnpc.isnull().values.all(axis=1))
print(cnpc.isnull().values.sum(axis=0)) # 每列有多少个nan值
print(cnpc.isnull().values.sum(axis=1))# 每行有多少个nan值
print(cnpc.isnull().values.sum()) # 总共有多少个nan值

'''填补缺失值'''
cnpc.dropna(how='all',inplace=True)
# print(cnpc.head())
# cnpc.replace(np.nan,0,inplace=True)
cnpc['High'].fillna(cnpc['High'].mean(),inplace=True) #fill in with mean
# cnpc['Low'].fillna(method='ffill',inplace=True) #fill in with value from previous row
# cnpc['Close'].fillna(method='bfill',inplace=True) # fill in with value from the row behind
print(cnpc)

'''计算涨跌额'''
# 涨跌额是指当日股票价格与前一日收盘价格相比的涨跌数值。
# 添加一列change,其为当日close价格与之前一天的差值。当然注意这里数据有缺失,有的日期没有记录。
# print(cnpc.Close-cnpc.Close.shift())
change = cnpc.Close.diff()
change.fillna(change.mean(),inplace=True)

#插入列
# cnpc.insert(6,'change', change)
cnpc['Change'] = change
# print(cnpc)
# 按涨跌额排序,未改变sh,若需要,可以`inplace=True`
print(cnpc.sort_values(by='Change',ascending=False).head(3))

# 用shift方法错位
# cnpc['pct_change'] = ((cnpc['Change'].shift(-1)-cnpc['Change']) / cnpc['Change'])
# 或用pct_Change函数
cnpc['pct_change'] = cnpc.Change.pct_change()
cnpc.iloc[5:9]

format = lambda x: '%.2f' % x
# cnpc = cnpc.applymap(format)
cnpc = cnpc.applymap(float) # 可以重新把数据类型转换为float类型

def f(x):
    return pd.Series([x.min(),x.max(),x.max()-x.min()],index=['min','max','range'])
# cnpc.apply(f)

# 按月分组
cnpc['group_index'] = cnpc.index.map(lambda x: 100*x.year + x.month)

# 对不同的列运用不同的函数聚合
def peak_to_peak(arr):
    return arr.max() - arr.min()
grouped = cnpc.groupby('group_index').agg({
        'Open' : peak_to_peak,
        'High' : 'max',
        'Low' : 'min',
        'Change' : 'mean'
    })

# grouped_1 = cnpc.groupby(pd.TimeGrouper("M")).agg({
#         'Open' : peak_to_peak,
#         'High' : 'max',
#         'Low' : 'min',
#         'Change' : 'mean'
#     })

cnpc.describe() # 数据整体概览

'''可以把相似度高的维度删掉‘’‘
part=cnpc[['Open', 'High', 'Low', 'Close','Volume']]
cov = np.corrcoef(part.T) # 通过矩阵的转置
print(cov)
img = plt.matshow(cov,cmap=plt.cm.winter)
plt.colorbar(img, ticks=[-1,0,1])
plt.show()

pandas的输出问题

关于Python数据分析中pandas模块在输出的时候,每行的中间会有省略号出现,和行与行中间的省略号....问题,其他的站点(百度)中的大部分都是瞎写,根本就是复制黏贴以前的版本,你要想知道其他问题答案就得去读官方文档吧:https://pandas.pydata.org/pandas-docs/stable/user_guide/options.html

如果数据行很多的话,对于pandas模块是自动默认只显示100行数据,如果超100行,例如120行,则中间的20行会被“ ... ”替代!

先处理pandas 读取数据后在行中间省略部分的处理:

#显示被省略的列
pd.set_option('display.width',None)

#最大显示所有行
pd.set_option('display.max_rows',None)