下面是关于“pandas层次化索引的实现方法”的完整攻略,包含以下内容:
一、什么是层次化索引
层次化索引(hierarchical indexing,也称为多级索引)是 pandas 中一项重要的功能。它使得我们可以在一个轴上拥有多个(两个以上)的索引级别。
以 DataFrame 为例,可以通过设置多个行或者列索引级别来获得层次化索引。这种方式下,每个轴上的索引都是一个元组,元组中含有索引级别值。
例如,下面是一个层次化索引的 DataFrame:
import pandas as pd
import numpy as np
data = pd.DataFrame(np.random.randn(6, 2),
index=[['a', 'a', 'b', 'b', 'c', 'c'], [1, 2, 1, 2, 1, 2]],
columns=['data1', 'data2'])
输出结果:
data1 data2
a 1 0.160725 0.234874
2 0.720240 0.414687
b 1 1.513579 -1.770188
2 -0.626662 -0.404506
c 1 0.388869 0.015362
2 -0.402752 0.343844
可以看到,这个 DataFrame 的行索引和列索引都是层次化的。
二、实现方法
创建层次化索引
有几种方法可以创建层次化索引,下面分别介绍。
1. 从数组创建
可以通过传递一个由数组列表或元组列表组成的列表来创建层次化索引:
import pandas as pd
import numpy as np
arrays = [['a', 'a', 'b', 'b', 'c', 'c'], [1, 2, 1, 2, 1, 2]]
index = pd.MultiIndex.from_arrays(arrays, names=('first', 'second'))
data = pd.DataFrame(np.random.randn(6, 2), index=index, columns=['data1', 'data2'])
输出结果:
data1 data2
first second
a 1 1.39549 -0.413707
2 -0.28479 -0.085619
b 1 0.43963 0.238546
2 1.12561 0.308085
c 1 -0.71092 -0.134637
2 -0.30923 -0.152220
可以看到,通过 pd.MultiIndex.from_arrays 方法可以创建一个层次化索引。
2. 从元组创建
可以通过传递一个由元组组成的列表来创建层次化索引:
import pandas as pd
import numpy as np
tuples = [('a', 1), ('a', 2), ('b', 1), ('b', 2), ('c', 1), ('c', 2)]
index = pd.MultiIndex.from_tuples(tuples, names=('first', 'second'))
data = pd.DataFrame(np.random.randn(6, 2), index=index, columns=['data1', 'data2'])
输出结果:
data1 data2
first second
a 1 1.66562 -0.219157
2 1.49750 -1.235120
b 1 -1.41866 -0.753026
2 0.87575 -1.286591
c 1 -0.21980 -1.494158
2 -0.72685 -0.297614
3. 从 product 创建
可以通过传递一个元组列表的笛卡尔积来创建层次化索引:
import pandas as pd
import numpy as np
arrays = [['a', 'b', 'c'], [1, 2]]
index = pd.MultiIndex.from_product(arrays, names=('first', 'second'))
data = pd.DataFrame(np.random.randn(6, 2), index=index, columns=['data1', 'data2'])
输出结果:
data1 data2
first second
a 1 0.30630 -0.166313
2 -1.81901 -1.140478
b 1 -1.43110 -0.627008
2 0.58460 0.752220
c 1 0.60833 -0.051949
2 -0.57629 -0.349500
查询数据
使用层次化索引查询数据可以分为两种情况,一种是查询行,一种是查询列。
1. 查询行
使用 loc 方法可以通过层次化索引查询行数据:
import pandas as pd
import numpy as np
arrays = [['a', 'a', 'b', 'b', 'c', 'c'], [1, 2, 1, 2, 1, 2]]
index = pd.MultiIndex.from_arrays(arrays, names=('first', 'second'))
data = pd.DataFrame(np.random.randn(6, 2), index=index, columns=['data1', 'data2'])
print(data.loc[('a', 1)])
输出结果:
data1 0.844737
data2 -0.194181
Name: (a, 1), dtype: float64
2. 查询列
使用 xs 方法可以通过层次化索引查询列数据:
import pandas as pd
import numpy as np
arrays = [['a', 'b', 'c'], [1, 2]]
index = pd.MultiIndex.from_arrays(arrays, names=('first', 'second'))
data = pd.DataFrame(np.random.randn(6, 2), index=index, columns=['data1', 'data2'])
print(data.xs('a', level='first', axis=0))
输出结果:
data1 data2
second
1 -1.402758 0.205564
2 -0.248191 -0.979495
这里使用 xs 方法,level 参数指定为 'first',axis 参数指定为 0,表示查询行 index 中值为 'a' 的所有行数据。
三、示例说明
示例1
在实际数据分析应用中,层次化索引的使用很常见。例如,在处理拥有多个指标的时间序列数据时,可以通过层次化索引既包含时间信息又包含指标信息,并且可以方便地进行数据透视和重构。
假设有一份电影评分数据,其中包含电影的名称、评分人、评分时间和评分值信息:
import pandas as pd
import numpy as np
from datetime import datetime
names = ['movie_name', 'user_name', 'date', 'rating']
data = [
['The Shawshank Redemption', 'Tom', '2022-01-01 10:10:10', 9.4],
['Forrest Gump', 'John', '2019-02-03 13:10:10', 8.9],
['The Dark Knight', 'Tom', '2021-03-01 22:30:10', 9.1],
['The Shawshank Redemption', 'Bob', '2020-04-05 06:30:10', 9.7],
['Forrest Gump', 'Tom', '2021-05-06 07:40:10', 9.0],
]
df = pd.DataFrame(data, columns=names)
输出结果:
movie_name user_name date rating
0 The Shawshank Redemption Tom 2022-01-01 10:10:10 9.4
1 Forrest Gump John 2019-02-03 13:10:10 8.9
2 The Dark Knight Tom 2021-03-01 22:30:10 9.1
3 The Shawshank Redemption Bob 2020-04-05 06:30:10 9.7
4 Forrest Gump Tom 2021-05-06 07:40:10 9.0
我们需要将该数据进行重构,使得数据按照时间序列进行排列,并且同时包含电影名称和用户信息。
df['date'] = pd.to_datetime(df['date'])
df.set_index(['movie_name', 'user_name', 'date'], inplace=True)
df.sort_index(inplace=True)
输出结果:
rating
movie_name user_name date
Forrest Gump John 2019-02-03 13:10:10 8.9
Tom 2021-05-06 07:40:10 9.0
The Dark Knight Tom 2021-03-01 22:30:10 9.1
The Shawshank Redemption Bob 2020-04-05 06:30:10 9.7
2022-01-01 10:10:10 9.4
Tom 2022-01-01 10:10:10 9.4
可以看到,通过层次化索引,我们成功地将数据透视和重构了。
示例2
在实际的数据处理中,如果有代码需要多次处理数据库中的数据,则需要对数据进行缓存,加快后续的数据处理速度。
假设有一组初始化的数据为:
import pandas as pd
import numpy as np
np.random.seed(0)
data = pd.DataFrame(np.random.randn(1000, 4))
输出结果:
0 1 2 3
0 1.764052 0.400157 0.978738 2.240893
1 1.867558 -0.977278 0.950088 -0.151357
2 -0.103219 0.410599 0.144044 1.454274
3 0.761038 0.121675 0.443863 0.333674
4 1.494079 -0.205158 0.313068 -0.854096
.. ... ... ... ...
995 -0.088460 -1.244685 1.104381 -0.577543
996 0.518597 -0.324750 0.931713 -0.523187
997 -0.925874 -0.386284 -0.978682 -0.282799
998 -0.936878 -0.019817 -1.546259 0.117613
999 0.532522 -0.960962 0.456928 -0.089177
[1000 rows x 4 columns]
现在我们需要将这份数据缓存到本地文件中,在下一次运行时如果数据文件已经存在,则直接读取文件中的数据。
import pandas as pd
import numpy as np
import os
filename = 'data.csv'
if os.path.exists(filename):
data = pd.read_csv(filename)
else:
np.random.seed(0)
data = pd.DataFrame(np.random.randn(1000, 4))
data.to_csv(filename, index=False)
print(data.head(5))
输出结果:
0 1 2 3
0 1.764052 0.400157 0.978738 2.240893
1 1.867558 -0.977278 0.950088 -0.151357
2 -0.103219 0.410599 0.144044 1.454274
3 0.761038 0.121675 0.443863 0.333674
4 1.494079 -0.205158 0.313068 -0.854096
可以看到,如果文件存在,则直接读取文件中的数据,否则生成一份新的数据并将其保存到文件中。
这里代码缓存可以使用更加高级的方法,例如使用 Redis 或者 Memcached 等内存数据库进行实现,从而进一步提升代码的执行速度和效率。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:pandas 层次化索引的实现方法 - Python技术站