Pandas数据排序
.sort_index() 在指定轴上根据索引进行排序,索引排序后内容会跟随排序
b = pd.DataFrame(np.arange(20).reshape(4,5),index=['c','a','d','b']) b.sort_index() # 默认按行索引排序,默认升序 b.sort_index(ascending=False) b.sort_index(axis=1,ascending=False) # 按列索引排序,降序
sort_values() 按值排序
dates = pd.date_range('20130101', periods = 10) df = pd.DataFrame(np.random.randn(10,4), index = dates, columns = ['A','B','C','D']) df.sort_values(by='A') # 指定排序基准列 df.sort_values(by='A', ascending=False) # 倒序 # 按列排序(一行的所有列) df.sort_values(axis=1, by='2013-01-01', ascending=False)
关于排序中的缺失值问题
排序不论升序降序,缺失值永远排在最后
a = pd.DataFrame(np.arange(12).reshape(3,4), index=['a','b','c']) a b = pd.DataFrame(np.arange(20).reshape(4,5), index=['c','a','d','b']) b c = a + b c.sort_values(by=0) # 升序,缺失值在最后 c.sort_values(by=0, ascending=False)# 降序,缺失值还在最后
随机排列和随机采样
随机排列
利用numpy.random.permutation函数可以实现对Series或DataFrame的列的随机排序工作(permuting,随机重排序)
通过需要排列的轴的长度调用permutation,可产生一个表示新顺序的整数数组:
# 随机排列序列 a = [1,2,3,4,5,6,7] np.random.permutation(a) df = pd.DataFrame(np.arange(5 * 4).reshape((5, 4))) df.index df.columns.values # 打乱行索引 np.random.permutation(df.index) df.loc[np.random.permutation(df.index)] # 随机重排行索引和列索引 index = np.random.permutation(df.index) index columns = np.random.permutation(df.columns.values) columns df.loc[index,columns]
随机采样
choice(),从一个序列中随机抽取某些值
a = [1,2,3,4,5,6,7] np.random.choice(a) np.random.choice(a,size=3,replace=False) # 保证这三次取出的没用重复值 # 按行索引采样 df.loc[np.random.choice(df.index,size=2,replace=False)] # 按行、按列随机采样 index = np.random.choice(df.index,size=3,replace=False) columns = np.random.choice(df.columns.values,size=2,replace=False) df.loc[index,columns]
重新索引(修改索引)¶
reindex() ,重新索引,创建一个适应新索引的新对象
一种变相的查询方式,类似在查询中加入新行新列
- 直接赋值修改索引
- set_index(), reset_index():普通行列和索引互相转换
- rename是将原索引某些值替换为新值
- reindex则是将整个索引重建(并不替换索引值,而是增减索引或改变顺序,原索引对应的值关系不变)
- reindex可以理解为一种查询方式
- loc查询如果索引值不存在,会报警告
- reindex查询如何索引值不存在,会新增一行或一列新值,值为缺失值
- reindex可以理解为一种查询方式
1.set_index DataFrame可以通过set_index方法,可以设置单索引和复合索引。 DataFrame.set_index(keys, drop=True, append=False, inplace=False, verify_integrity=False) append添加新索引,drop为False,inplace为True时,索引将会还原为列。
b = pd.DataFrame(np.arange(20).reshape(4,5),index=['c','a','d','b']) b.set_index(4) #指定列索引 b.set_index([4,3])
2.reset_index
reset_index可以还原索引,重新变为默认的整型索引
DataFrame.reset_index(level=None, drop=False, inplace=False, col_level=0, col_fill=”)
level控制了具体要还原的那个等级的索引
drop为False则索引列会被还原为普通列,否则会丢失
reset_index可以还原索引,重新变为默认的整型索引
DataFrame.reset_index(level=None, drop=False, inplace=False, col_level=0, col_fill=”)
level控制了具体要还原的那个等级的索引
drop为False则索引列会被还原为普通列,否则会丢失
bb = b.set_index([4,3]) bb.reset_index()
直接修改索引
有问题,不合适
- 索引修改后,值没有跟着变化
- 修改值必须和原索引长度保持一致,不能增加或删除索引
obj = pd.Series([4.5,7,2,-5.3], index=['d','b','a','c']) obj.index #obj.index.values obj.index=['a','b','c','d'] # obj.index = ['a','b','c'] # 长度不一致,报错
使用rename修改索引
只能替换已有索引
obj.rename({'a': 'aaa', 'b': 'bbb', 'x': 'xx'})
正规做法:使用reindex()重新索引
obj.reindex(['b', 'd', 'a']) # 删除值 obj.reindex(['a','b','c','d','e']) # 增加值 obj.reindex(['a','b','c','d','e'],fill_value=0) # example obj2 = pd.Series(['blue','purple','yellow'], index = [0,2,4]) obj2 obj2.reindex(range(6),fill_value=0) # 前向,后向填充 obj2.reindex(range(6), method='ffill') obj2.reindex(range(6), method='bfill')
DataFrame索引重建
# 重建行索引 frame.reindex(['数学', '英语', '语文']) frame.reindex(['数学', '编程', '语文']) frame.reindex(index=['数学', 'english', '语文']) # 重建行列索引 frame.reindex(['张三', '赵六', '王五'], axis=1) frame.reindex(columns=['张三', '赵六', '王五']) # 行&列 frame.reindex(index=['语文', '编程', '英语'], columns=['张三', '赵六', '王五'])
# 索引可以直接赋值修改,但是不能直接修改单个索引 frame.index = [1,2,3] frame.columns = [1,2,3] frame.reindex(index=[1,2,10,4], columns=[3,1,5,2])
带有重复值的轴索引
许多Pandas函数要求标签唯一,但这不是强制的
obj = pd.Series(range(5), index=['a','a','b','b','c']) obj obj.index.is_unique
Pandas数据规整 - 转换 - 层次化索引
层次化索引(hierarchical indexing)使你能在一个轴上拥有超过1个索引级别,
多层索引可以对数据结构升维,能以低维度形式处理高维度数据
用多层索引 (Multi-index) 的 Series/DataFrame,存储2维/3维或以上维度的信息
Pandas的三维以上数据处理:
一起使用三维以上数据类型:面板数据(panel)处理,这个数据类型已被废弃
维度不高的可用层次化索引,
维度高的可以使用pydata出品的专用库 xarray 处理(其数据类型可以和Pandas互相转换)
Series层次化索引的查询
data = pd.Series(np.random.randn(9), index=[['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd'], [1, 2, 3, 1, 3, 1, 2, 2, 3]]) data # 默认索引 data[0] # 查询单值 data[[0, 3]] # 查询多值 data[1:4] # 切片 # 自定义索引,默认查询外层索引 data['a'] # 查询单值 data[['a', 'c']] # 查询多值 data['a':'c'] # 切片
将层次化索引的Series转为DataFrame
多层索引的 Series 其实和 DataFrame 维度一样,只是展示形式不同
重塑就是通过改变数据表里面的 行索引 和 列索引 来改变展示形式
data.unstack() # 自定义索引,默认查询外层索引 data.unstack()[1] # 查询列 data.unstack().loc['a'] # 查询行 data.unstack().loc['a', 2] # 行,列 # DataFrame交换 data.unstack() data.unstack().T # Series交换 data.unstack().T.stack() data.unstack().unstack().dropna()
使用DataFrame的列或行进行索引(重要)
使用set_index()将DataFrame的一个或多个列当做行索引来用,或者将行索引变成DataFrame的列
frame2 = pd.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]} ) frame2.set_index('a') frame3 = frame2.set_index(['c', 'd']) frame2.set_index(['c', 'd'], append=True) # 增加索引,非替换,保留原索引 frame2.set_index(['c', 'd'], drop=False) # 列转索引后,保留原列 #行索引转为普通列 frame3.reset_index() #frame2转换列索引 # 先将原表转置,修改行索引后,再转置 frame2.T.set_index(0, append=True).T
通过修改行列索引值实现层次化索引
symbol = ['BABA', 'JD', 'AAPL', 'MS', 'GS', 'WMT'] data = {'行业': ['电商', '电商', '科技', '金融', '金融', '零售'], '价格': [176.92, 25.95, 172.97, 41.79, 196.00, 99.55], '交易量': [16175610, 27113291, 18913154, 10132145, 2626634, 8086946], '雇员': [101550, 175336, 100000, 60348, 36600, 2200000]} df2 = pd.DataFrame(data, index=symbol) df2.name='美股' df2.index.name = '代号' # 正确:使用MultiIndex赋值 df2.index = pd.MultiIndex.from_tuples( [('中国公司','BABA'), ('中国公司','JD'), ('美国公司','AAPL'), ('美国公司','MS'), ('美国公司','GS'), ('美国公司','WMT')], names=('country', 'company'), ) # 没有列索引层次化方法,可以转置后操作原列索引 df2x = df2.T df2x.index = pd.MultiIndex.from_tuples([('aaa', '行业'),('aaa','价格'),('bbb','交易量'),('bbb','雇员')], names=('ab', '情况')) df2x.T
直接创建多层索引DataFrame
frame = pd.DataFrame( np.arange(12).reshape((4, 3)), index=[['a', 'a', 'b', 'b'], [1, 2, 1, 2]], columns=[['Ohio', 'Ohio', 'Colorado'],['Green', 'Red', 'Green']], ) frame.index.names = ['key1', 'key2'] frame.columns.names = ['state', 'color'] # 或者这样创建 midx = pd.MultiIndex( levels=[['a', 'b'], [1, 2]], codes=[[0, 0, 1, 1], [0, 1, 0, 1]], names=['key1', 'key2'] ) mcol = pd.MultiIndex( levels=[[ 'Colorado', 'Ohio'], ['Green', 'Red']], codes=[[1, 1, 0],[0, 1, 0]], names=['state', 'color'] ) frame = pd.DataFrame( np.arange(12).reshape((4, 3)), index=midx, columns=mcol, )
DataFrame层次化索引查询
# 简陋查询,-->列 frame['Ohio'] frame['Ohio','Red'] # 外列-内列' # loc frame.loc['a'] # 外行 返回dataframe frame.loc['a','Ohio'] # 外行-外列 返回dataframe frame.loc['a',2] #外行-内行 返回Series # 外层行,内层行,外层列,内层列 ,2维series可以unstack为dataframe frame.loc['a', 1]['Ohio', 'Red'] # 外层行,外层列,内层行,内层列 frame.loc['a', 'Ohio'].loc[1, 'Red']
重排与分级排序
调整某条轴上各级别的顺序,或根据指定级别上的值对数据进行排序
frame.swaplevel() # 默认交换行索引 frame.swaplevel('key2', 'key1') # 手动指定调换索引name frame.swaplevel('key1', 'key2') # 交换顺序,效果一样 frame.swaplevel(0, 1) # 手动指定调换索引层级 frame.swaplevel(1, 0) frame.swaplevel(axis=1) # 交换列索引 frame.sort_index(ascending=False) # 行索引排序(优先最外层索引) frame.sort_index(ascending=False, level='key2') # 排序索引层级 frame.sort_index(ascending=False, axis=1) # 列索引排序
根据级别汇总统计
许多对DataFrame和Series的描述和汇总统计函数都有一个level选项,它用于指定在某条轴上计算的级别
其实是利用了pandas的groupby功能
frame.sum() # 按行求和 frame.sum(level='key1') # 以key1索引分组求和 # 用groupby实现 # 以外层行索引为分组基准a frame.groupby('key1').sum() # 分组基准,行索引name frame.groupby(level='key1').sum() # level传入分组基准 frame.groupby(['a', 'a', 'b', 'b']).sum() # 手动构造分组基准 # 以内层行索引为分组基准 frame.groupby('key2').sum() # 分组基准,行索引name frame.groupby(level='key2').sum() # level传入分组基准 frame.groupby([1,2,1,2]).sum() # 手动构造分组基准 frame.sum(axis=1) # 按列求和 #以内层列索引为基准实现 frame.sum(axis=1, level='color') # 两个 Green 相加 # 用分组实现 frame.groupby(['Green', 'Red', 'Green'], axis=1).sum() frame.groupby(axis=1, level='color').sum() #以外层列索引为基准 frame.sum(axis=1, level='state') # Ohio下的两列相加 frame.groupby(level='state', axis=1).sum().sort_index(ascending=False, axis=1) # 和上面的区别:使用手打的分组基准代替level定义 # 报错,直接传入分组索引值,默认使用最里层列索引 # frame.groupby(['Ohio', 'Ohio', 'Colorado'], axis=1).sum().sort_index(ascending=False, axis=1) # 列索引交换层级 frame.swaplevel(axis=1) frame.swaplevel(axis=1).groupby(['Ohio', 'Ohio', 'Colorado'], axis=1).sum().sort_index(ascending=False, axis=1)