数据结构之DataFrame
表格型数据结构,相当于一个二维数组,含有一组有序的列也可以看作是由Series组成
基本使用
# 创建DataFrame有很多中方式,但是一般情况下我们都不需要自己创建DataFrame而是将excel文件直接导入成DataFrame
# 方式1 传字典。字典的键会变成表格的列名称,行名称默认是索引
res = pd.DataFrame({'one':[1,2,3,4],'two':[4,3,2,1]})
res
one two
0 1 4
1 2 3
2 3 2
3 4 1
# 取值
res['one'] # 默认是Series的展示形式
0 1
1 2
2 3
3 4
Name: one, dtype: int64
res[['two']] # 再加[]就会变成表格的形式
two
0 4
1 3
2 2
3 1
res['two'][1] # 第一个中括号里面是列 第二个中括号是行
3
# res['two',1] # 不能按照numpy的行列方式书写了 会报错
# 方式2:直接传Series 如果Series有自定义的标签 那么生成的DataFrame列名称采用的就是标签名
res1 = pd.DataFrame({
'one':pd.Series([1,2,3],index=['c','b','a']),
'two':pd.Series([1,2,3],index=['b','a','c'])
})
res1
one two
a 3 2
b 2 1
c 1 3
# 方式3:自定义行列 index行 columns列
pd.DataFrame(np.array([[10,20,30],[40,50,60]]),index=['a','b'],columns=['c1','c2','c3'])
c1 c2 c3
a 10 20 30
b 40 50 60
# 方式4:列表中有几个元素就会生成几行数据 不指定行列默认都是用索引表示
pd.DataFrame([np.arange(1,8),np.arange(11,18),np.arange(21,28)])
0 1 2 3 4 5 6
0 1 2 3 4 5 6 7
1 11 12 13 14 15 16 17
2 21 22 23 24 25 26 27
# 方式5:会自动找行列的对应位置 没有的用NaN表示缺失值
s1 = pd.Series(np.arange(1,9,2))
s2 = pd.Series(np.arange(2,10,2))
s3 = pd.Series(np.arange(5,7),index=[1,2])
pd.DataFrame({'c1':s1,'c2':s2,'c3':s3})
c1 c2 c3
0 1 2 NaN
1 3 4 5.0
2 5 6 6.0
3 7 8 NaN
'''以上创建方式都仅仅做一个了解即可,因为工作中dataframe的数据一般都是来自于读取外部文件数据,而不是自己手动去创建'''
常见属性及方法
1.index 行索引
2.columns 列索引
3.T 转置
4.values 值索引
5.describe 快速统计
# index获取行索引
df.index
# columns获取列索引
df.columns
# T转置 行列互换
df.T
# values获取表格数据 组织成二维数组的形式
df.values
# describe常见的数学统计
df5.describe()
如何读取外部excel文件数据到DataFrame中
pd.read_csv(文件路径) # 将excel数据转换成pandas中的DataFrame
# 如果当前文件跟excel文件在同一个目录下所以可以直接写文件名
# 如果不在同一个路径下 那么需要输入excel文件的绝对路径
# '''
# 绝对路径
# 类似于全球具体坐标,任何人拿到该坐标都可以查找
# 相对路径
# 相对于一个参照物,并不是所有人都可以根据该坐标找到
# '''
#在读取excel数据到pandas中会自动给数据加上一个行索引(默认是从0开始的索引值)
#你还可以自己指定行索引(这个索引必须在表格中存在)
#方式1
pd.read_csv(文件路径,index_col='字段名')
#方式2
df = pd.read_csv(文件路径)
df.set_index('字段名')
# 取头部多条数据
df.head()
# 取尾部多条数据
df.tail()
# 查看行
df.index
# 查看列
df.columns
'''在使用matplotlib画图的时候需要经常用到 用以确定x轴和y轴'''
# 将DataFrame数据导出到excel表格中
df.to_csv(文件路径, index=False)
# index参数的意思就是是否保留行索引
# 默认index=True 自动将DataFrame的行索引也导出
数据操作
# 获取数据
#第一个中括号里面放的是列索引/列名称/列字段
df['列名称'] # 结果会是一个Series
df[['列名称']] # 结果会是一个DataFrame
df[['列名称1','列名称2','列名称3']] # 一次性获取多个列名称
# 切片操作(针对的是数据的条数)
df[0:10]
# 切片和获取列数据结合使用
df[2:4][['列名称1','列名称2']]
# 精确获取单元格中的数据
df.at['行值','列值']
# 简单的数学计算筛选
df[(df.列名称1>4)&(df.列名称2<15)]
排序
#升序降序
df.sort_values(['列名1','列名2'],ascending=True)
df.sort_values(['列名1','列名2'],ascending=False)
# 后面还可以对排序之后的结果筛选
df.sort_values(['列名1','列名2'],ascending=True)[['目标列1','目标列2']]
行列操作
#修改列名称
df.rename({'旧列名称':'新列名称'},axis='columns')
#修改行序列
df.rename({'旧列名称':'新列名称'},axis='index')
# 创建新的列 默认都是在尾部添加
df['新列名称']=新数据
df['新列名称']=df.列名称/(df.列名称1+df.列名称2)
'''右侧可以是自己写的数据 也可以是表格中其他字段计算的值'''
# 自定义配置
df.insert(3,'新列名称',新数据)
# 添加行 两者数据类型最好保持一致 本质其实就相当于拼接表格数据
df3 = df1.append(df2) # 方式1 append
pd.concat([df1,df2]) # 方式2 concat功能更强大 可以拼接Series和DataFrame
# 拷贝
df.copy()
时间序列处理
时间序列类型
1.时间戳
2.具体日期
3.时间间隔
# 灵活处理时间对象dateutil包
import dateutil #调用方法
dateutil.parser.parse("2019 Jan 2nd") # 这中间的时间格式一定要是英文格式
运行结果:
datetime.datetime(2019, 1, 2, 0, 0)
# 日期批处理
pd.to_datetime(['2018-03-01','2019 Feb 3','08/12-/019'])
运行结果:
DatetimeIndex(['2018-03-01', '2019-02-03', '2019-08-12'], dtype='datetime64[ns]', freq=None)
# 产生一个DatetimeIndex对象
# 转换时间索引
ind = pd.to_datetime(['2018-03-01','2019 Feb 3','08/12-/019'])
sr = pd.Series([1,2,3],index=ind)
sr
运行结果:
2018-03-01 1
2019-02-03 2
2019-08-12 3
dtype: int64
# 转换为array数组
pd.to_datetime(['2018-03-01','2019 Feb 3','08/12-/019']).to_pydatetime()
运行结果:
array([datetime.datetime(2018, 3, 1, 0, 0),
datetime.datetime(2019, 2, 3, 0, 0),
datetime.datetime(2019, 8, 12, 0, 0)], dtype=object)
# 产生时间对象数组:date_range
pd.date_range("2019-1-1","2019-1-15")
运行结果:
DatetimeIndex(['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04',
'2019-01-05', '2019-01-06', '2019-01-07', '2019-01-08',
'2019-01-09', '2019-01-10', '2019-01-11', '2019-01-12',
'2019-01-13', '2019-01-14', '2019-01-15'],
dtype='datetime64[ns]', freq='D')
'''
补充
1.传入年或者年月作为切片方式
2.传入日期范围作为切片方式
3.丰富的函数支持:resample(),strftime(),...
4.批量转换为datetime对象:to_pydatetime()
# 记住
a.resample("3D").mean() # 计算每三天的均值
a.resample("3D").sum() # 计算每三天的和
'''
分组与聚合
df = pd.DataFrame({
'key1':['x','x','y','y','x'],
'key2':['one','two','one','two','one'],
'data1':np.random.randn(5),
'data2':np.random.randn(5)})
f1 = df['data1'].groupby(df['key1']) # groupby分组
f1.mean() # 调用mean函数求出平均值
f2 = df['data1'].groupby([df['key1'],df['key2']])
f2.mean()
运行结果:
key1 key2
x one 0.083878
two 0.872437
y one -0.665888
two -0.144310
Name: data1, dtype: float64
f2.mean().unstack()
运行结果:
key2 one two
key1
x 0.083878 0.872437
y -0.665888 -0.144310
# 通过unstack方法就可以让索引不堆叠在一起了
聚合函数的自定义
# 使用自定义的聚合函数,需要将其传入aggregate或者agg方法当中
def peak_to_peak(arr):
return arr.max() - arr.min()
f1.aggregate(peak_to_peak)
运行结果:
key1
x 3.378482
y 1.951752
Name: data1, dtype: float64
多个聚合函数联合使用
f1.agg(['mean','std'])
运行结果:
mean std
key1
x -0.856065 0.554386
y -0.412916 0.214939
"""
总结
聚合函数的时候 单个情况下可以直接点击函数名
df.sum()
如果想要执行多个聚合函数
df.agg(['mean','sum']) 多个
df.agg(['mean']) 单个
"""
pandas的一点爬虫知识
"""
HTML页面
一堆html标签组成
获取HTML页面上的table标签里面的数据
read_html
"""
pd.read_html('网页地址')
# 针对table标签可以直接将里面的数据爬取下来
res = pd.read_html('https://baike.baidu.com/item/NBA%E6%80%BB%E5%86%A0%E5%86%9B/2173192?fr=aladdin')
# 返回的是一个python列表 表格与表格数据用逗号隔开
# 获取有效数据
champion = res[0] # 索引取值获取对应的表格数据
# 拿到的表格数据 默认的列索引是从0开始的普通索引值
# 将列索引用表格的第一行数据代替
champion.columns = champion.iloc[0]
# 将原来第一行数据删除
champion.drop([0],inplace=True)
# 针对冠军字段分组
champion.groupby('冠军').groups # 查看分组之后对象里面的大致信息
# 获取分组之后的各分组大小
champion.groupby('冠军').size()
# 获取各组冠军次数
champion.groupby('冠军').size().sort_values(ascending=False) # 升序
# 分组字段可以一次性取多个
champion.groupby(['冠军', 'FMVP']).size()