1、Pandas创建Series(只有行索引)数据类型
Pandas官方文档网址:https://pandas.pydata.org/
安装Pandas
pip install -i https://pypi.douban.com/simple pandas
导入Pandas库,一般都会用到numpy库,所以我们一同导入:
import numpy as np
import pandas as pd
创建Series 数据类型有三种方法:
- 通过列表创建Series对象
- 通过numpy的对象Ndarry创建Serise
- 通过字典创建Series对象;字典的所有key值作为索引,所有的value值作为Series值
import pandas as pd
import numpy as np
import string
# 查看版本
# print(pd.__version__)
# *************创建Series对象***************
# 1). 通过列表创建Series对象
array = ["粉条", "粉丝", "粉带"]
# 如果不指定索引,默认从0开始
s1 = pd.Series(data=array)
print(s1)
ss1 = pd.Series(data=array, index=['A', 'B', 'C'])
print(ss1)
# 2). 通过numpy的对象Ndarry创建Serise
n = np.random.randn(5) # 随机创建一个ndarray对象
s2 = pd.Series(data=n)
print(s2)
# 修改元素的数据类型
ss2 = s2.astype(np.int)
print(ss2)
# 3). 通过字典创建Series对象;字典的所有key值作为索引,所有的value值作为Series值
dict = {string.ascii_lowercase[i]:i for i in range(5)}
print(dict)
s3 = pd.Series(dict)
print(s3)
0 粉条
1 粉丝
2 粉带
dtype: object
A 粉条
B 粉丝
C 粉带
dtype: object
0 1.194158
1 0.125505
2 2.392429
3 0.155327
4 -0.408286
dtype: float64
0 1
1 0
2 2
3 0
4 0
dtype: int64
{'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4}
a 0
b 1
c 2
d 3
e 4
dtype: int64
2、Series基本操作
Series 基本操作:
编号 属性或方法 描述
1 axes 返回行轴标签列表。
2 dtype 返回对象的数据类型(dtype)。
3 empty 如果系列为空,则返回True。
4 ndim 返回底层数据的维数,默认定义:1。
5 size 返回基础数据中的元素数。
6 values 将系列作为ndarray返回。
7 head() 返回前n行。
8 tail() 返回最后n行。
import numpy as np
import pandas as pd
array = ['粉条', '粉丝', '粉带']
s = pd.Series(data=array)
print(s)
# print(s.axes) # 返回行轴标签列表
# print(s.dtype) # 返回对象的数据类型
# print(s.empty) # 如果系列为空,则返回True
# print(s.ndim) # 返回底层数据的维数,默认定义:1
# print(s.size) # 返回基础数据中的元素数
# print(s.values) # 获取所有的value值(不含索引)
# 1).修改Series索引
print(s.index)
s.index = ['A', 'B','C']
print(s)
# 2). Seriess纵向拼接
array = ['粉条', '粉丝', 'westos']
# 如果不指定索引,默认从0开始
s1 = pd.Series(data=array)
s2 = s.append(s1)
print(s2)
# 3).删除指定索引对应的元素
s3 = s2.drop('C')
print(s3)
# 4).根据指定的索引查找元素
print(s3['B'])
s3['B'] = np.nan ## None, null, pandas数据为空, 或者数据缺失, np.nan
print(s3)
# 5).切片操作 --- 同列表
print(s3[:2])
print(s3[::-1])
print(s3[-2:])
3、Series运算(+ - * /)
import pandas as pd
import numpy as np
s1 = pd.Series(np.arange(5), index=['a', 'b', 'c', 'd', 'e'])
s2 = pd.Series(np.arange(2,8), index=['c', 'd', 'e', 'f', 'g', 'h'])
print(s1)
print(s2)
# 按照对应的索引来进行运算,如果索引不同,则填充为Nan
# 加法, 缺失值 + 真实值 = 缺失值
# print(s1+s2)
print(s1.add(s2))
# 减法
# print(s1 - s2)
print(s1.sub(s2))
# 乘法
# print(s1 * s2)
print(s1.mul(s2))
# 除法
# print(s1 / s2)
print(s1.div(s2))
# 求中位数
print(s1)
print(s1.median())
# 求和
print(s1.sum())
# max
print(s1.max())
# min
print(s1.min())
a 0
b 1
c 2
d 3
e 4
dtype: int64
c 2
d 3
e 4
f 5
g 6
h 7
dtype: int64
a NaN
b NaN
c 4.0
d 6.0
e 8.0
f NaN
g NaN
h NaN
dtype: float64
a NaN
b NaN
c 0.0
d 0.0
e 0.0
f NaN
g NaN
h NaN
dtype: float64
a NaN
b NaN
c 4.0
d 9.0
e 16.0
f NaN
g NaN
h NaN
dtype: float64
a NaN
b NaN
c 1.0
d 1.0
e 1.0
f NaN
g NaN
h NaN
dtype: float64
a 0
b 1
c 2
d 3
e 4
dtype: int64
2.0
10
4
0
4、特殊的where方法
where方法:类似于三元运算符,满足条件不做改变,否则赋值为其他值
import pandas as pd
import numpy as np
# series中的where方法运行结果和numpy中完全不同;
s1 = pd.Series(np.arange(5), index=['a', 'b', 'c', 'd', 'e'])
# 判断s1的value值是否大于3, 如果大于3,值不变, 否则,设置为缺失值
print(s1.where(s1>3))
# 对象中不大于3的元素赋值为10;判断s1的value值是否大于3, 如果大于3,值不变, 否则,设置值为10
print(s1.where(s1>3, 10))
# 判断s1的value值是否大于3, 如果小于3,值不变, 否则,设置为缺失值
print(s1.mask(s1>3))
# 判断s1的value值是否大于3, 如果小于3,值不变, 否则,设置为10
print(s1.mask(s1>3, 10))
a NaN
b NaN
c NaN
d NaN
e 4.0
dtype: float64
a 10
b 10
c 10
d 10
e 4
dtype: int64
a 0.0
b 1.0
c 2.0
d 3.0
e NaN
dtype: float64
a 0
b 1
c 2
d 3
e 10
5、创建DataFrame数据类型
Series只有行索引,而DataFrame对象既有行索引,也有列索引
行索引,表明不同行,横向索引,叫index,
列索引,表明不同列,纵向索引,叫columns,
方法有三种:
- 通过列表创建
- 通过numpy对象创建
- 通过字典的方式创建
import pandas as pd
import numpy as np
# 方法1:通过列表创建
li = [
[1,2,3,4],
[2,3,4,5]
]
# DataFrame对象里面包含两个索引,行索引(0轴,axis=0),列索引(1轴,axis=1)
d1 = pd.DataFrame(data=li, index=['A','B'],columns=['views', 'loves', 'comments', 'tranfers'])
print(d1)
# 方法2:通过numpy对象创建
narr = np.arange(8).reshape(2,4)
d2 = pd.DataFrame(data=narr, index=['A','B'],columns=['views', 'loves', 'comments', 'tranfers'])
print(d2)
# 方法三:通过字典的方式创建
dict = {
'views':[1,2],
'loves':[2,3],
'comments':[3,4]
}
d3 = pd.DataFrame(data=dict, index=['A','B'])
print(d3)
# 日期操作的特例
# pd.date_range()
dates = pd.date_range(start='1/1/2020', end='1/5/2020')
print(dates)
#行索引
dates = pd.date_range(start='today',periods=6,freq='2D') # periods=6从今天开始向后产生6个日期
print(dates)
# 列索引
columns = ['A','B','C','D']
d4 = pd.DataFrame(data=np.random.randn(6,4),index=dates,columns=columns)
print(d4)
# 一维对象:建立一个以2020年的一天为索引,值为随机数
dates = pd.date_range(start='1/1/2020',end='1/3/2020',freq='D')
print(dates)
s1 = pd.Series(data=np.arange(3),index=dates)
print(s1)
views loves comments tranfers
A 1 2 3 4
B 2 3 4 5
views loves comments tranfers
A 0 1 2 3
B 4 5 6 7
views loves comments
A 1 2 3
B 2 3 4
DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04',
'2020-01-05'],
dtype='datetime64[ns]', freq='D')
DatetimeIndex(['2020-05-09 03:47:05.499954', '2020-05-11 03:47:05.499954',
'2020-05-13 03:47:05.499954', '2020-05-15 03:47:05.499954',
'2020-05-17 03:47:05.499954', '2020-05-19 03:47:05.499954'],
dtype='datetime64[ns]', freq='2D')
A B C D
2020-05-09 03:47:05.499954 -1.752169 -2.399516 -0.212687 -0.359451
2020-05-11 03:47:05.499954 -0.297410 -1.478582 -0.719484 -0.166028
2020-05-13 03:47:05.499954 0.792006 1.875343 -0.370601 1.184922
2020-05-15 03:47:05.499954 0.786631 1.970749 -1.022239 0.102846
2020-05-17 03:47:05.499954 -0.596685 -1.231768 -0.620204 0.465896
2020-05-19 03:47:05.499954 -1.178048 2.271825 0.943365 -1.896436
DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03'], dtype='datetime64[ns]', freq='D')
2020-01-01 0
2020-01-02 1
2020-01-03 2
Freq: D, dtype: int64
6、DataFrame基础属性和整体情况查询
a)基础属性
df.shape #行数、列数
df.dtype #列数据类型
df.ndim #数据维度
df.index #行索引
df.columns #列索引
df.values #对象值,二维ndarray数组
b)整体情况查询
df.head(3) #显示头部几行,默认5行
df.tail(3) #显示末尾几行,默认5行
df.info() #相关信息概览:行数、列数、索引、列非空值个数、列类型、内存占用
df.describe() #快速综合统计结果: 计数、均值、标准差、最大值、四分位数、最小值等
注意:
获取行数据: 不能直接通过行索引获取行数据,需通过切片获取,
- DataFrame对象[:1] 获取第一行数据
- DataFrame对象[:2] 获取前两行数据
或者通过:- DataFrame对象.iloc[0] 获取第一行数据,
- DataFrame对象.loc[‘A’] 获取标签为A的行数据
获取列数据:
- DataFrame对象[‘列标签名称’]
- DataFrame对象.列标签名称
import numpy as np
import pandas as pd
narr = np.arange(8).reshape(2, 4)
# DataFRame对象里面包含两个索引, 行索引(0轴, axis=0), 列索引(1轴, axis=1)
d1 = pd.DataFrame(data=narr, index=['A', 'B'], columns=['views', 'loves', 'comments', 'tranfers'])
print(d1)
# ********************1). 查看基础属性******************
print(d1.shape) # 获取数组的行数和列数
print(d1.dtypes) # 获取数组的数据类型
print(d1.ndim) # 获取数组的维度
print(d1.index) # 行索引
print(d1.columns) #列索引
print(d1.values, type(d1.values)) # 数组的值,数组的类型
# *******************2).数据整体情况的查询******************
print(d1.head(1)) #显示前1行,默认为5行
print(d1.tail(1)) #显示后1行,默认为5行
print('*' * 10)
# 相关信息的预览:行数、列数、列类型、内存占用
print('info:', d1.info())
print('统计:'.center(50,'*'))
# 快速综合统计结果:计数, 均值, 标准差, 最小值, 1/4位数, 中位数, 3/4位数, 最大值;
print(d1.describe())
# 3).转置操作
print('d1:\n',d1)
# print('d1 T:\n',d1.transpose())
# print('d1 T:\n',d1.T)
print('d1 T:\n',d1.swapaxes(1,0))
# 4). 按列进行排序
print(d1)
# 按照指定列进行排序, 默认是升序, 如果需要降序显示,设置ascending=False;
print(d1.sort_values(by=['views', 'tranfers'], ascending=False))
# 5). 切片及查询
print(d1)
print(d1[:2]) # 可以实现切片, 但是不能索引;
print('1:\n', d1['views']) # 通过标签查询, 获取单列信息
print('2:\n', d1.views) # 和上面是等价的;
print(d1[['views', 'comments']]) # 通过标签查询多列信息
# 6). 通过类似索引的方式查询
# -iloc(通过位置进行行数据的获取)
# -loc(通过标签索引获取行数据)
# print(d1[0]) # 报错
print(d1.iloc[0]) # 获取第一行数据
print(d1.iloc[-1]) #获取第二行数据
print(d1.loc['A']) # 通过标签索引获取行数据
# 7). 更改pandas的值
d1.loc['A'] = np.nan
print(d1)
print(d1.info())
7、文件的读取与写入
- 读csv文件:pd.read_csv()
- 写入csv文件:df.to_csv()
- 写入excel文件:df.to_excel()
import os
import pandas as pd
# 1). csv文件的写入
df = pd.DataFrame(
{'province': ['陕西', '陕西', '四川', '四川', '陕西'],
'city': ['咸阳', '宝鸡', '成都', '成都', '宝鸡'],
'count1': [1, 2, 3, 4, 5],
'count2': [1, 2, 33, 4, 5]
}
)
print(df)
filename = os.path.join('doc','csvFile.csv')
"""
index=True/False 是否存储行索引, 一般情况下不存储
mode='w' 文件写入的方式, 默认是'w'(清空原有的文件内容, 再写入), 'a'追加
header=True/False 是否写入头部信息(列索引), 一般情况是需要的
"""
# df.to_csv(filename, index=False, mode='a', header=False, sep=' ') # index=False不存储行索引
# print("csv文件保存成功")
df2 = pd.read_csv('doc/csvFile.csv')
print(df2)
# # 3). excel文件的写入
df.to_excel("doc/excelFile.xlsx", sheet_name="省份统计", index=False)
print("excel文件保存成功")
8、分组和聚合操作之group_by
pandas提供了一个灵活高效的groupby功能,
1). 它使你能以一种自然的方式对数据集进行切片、切块、摘要等操作。
2). 根据一个或多个键(可以是函数、数组或DataFrame列>名)拆分pandas对象。
3). 计算分组摘要统计,如计数、平均值、标准差,或用户自定义函数。
import pandas as pd
import numpy as np
df = pd.DataFrame(
{'province': ['陕西', '陕西', '四川', '四川', '陕西'],
'city': ['咸阳', '宝鸡', '成都', '成都', '宝鸡'],
'count1': [1, 2, 3, 4, 5],
'count2': [1, 2, 33, 4, 5]
}
)
# 陕西 咸阳 1
# 宝鸡 1
print(df)
# 根据某一列的key值进行统计
grouped = df['count1'].groupby(df['province'])
print(grouped.describe())
print(grouped.median())
# 根据城市统计分析count1的信息
grouped = df['count1'].groupby(df['city'])
print(grouped.max())
# 指定多个key值进行分类聚合
grouped = df['count1'].groupby([df['province'], df['city']])
print(grouped.max())
print(grouped.sum())
print(grouped.count())
# 通过unstack方法,实现层次化的索引
print(grouped.max().unstack())
Name: count1, dtype: int64
city 咸阳 宝鸡 成都
province
四川 NaN NaN 4.0
陕西 1.0 5.0 NaN
案例:消费金额与小费之间的关联与性别和吸烟与否的关系文件内容: 总消费金额, 小费金额, 性别, 是否抽烟, 日期, 时间, 星期
需求:
- 分别吸烟顾客与不吸烟顾客的消费金额与小费之间的散点图;
- 女性与男性中吸烟与不吸烟顾客的消费金额与小费之间的散点图关系;
import pandas as pd
filename = 'doc/tips.csv'
data = pd.read_csv(filename)
# # 女性中吸烟与不吸烟顾客的消费金额与小费之间的散点图关系;
is_smoker = data['smoker'] == 'Yes'
is_female = data['sex'] == 'Female'
female_smoker = data[is_female & is_smoker]
female_no_smoker = data[is_female & ~is_smoker]
male_smoker = data[~is_female & is_smoker]
male_no_smoker = data[~is_female & ~is_smoker]
#
# 3). 绘制散点图
from pyecharts import Scatter
scatter = Scatter("消费金额与小费之间的散点图")
scatter.add("吸烟女顾客", female_smoker['total_bill'], female_smoker['tip'])
scatter.add("不吸烟女顾客", female_no_smoker['total_bill'], female_no_smoker['tip'])
scatter.add("吸烟男顾客", male_smoker['total_bill'], male_smoker['tip'])
scatter.add("不吸烟男顾客", male_no_smoker['total_bill'], male_no_smoker['tip'])
scatter.render()