Pandas数据规整 - 转换

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查询如何索引值不存在,会新增一行或一列新值,值为缺失值

 

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则索引列会被还原为普通列,否则会丢失
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层次化索引

二维DataFrame转为多维

使用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)

 

posted @ 2020-08-12 15:14  亚洲哈登  阅读(265)  评论(0编辑  收藏  举报