Python Pandas - 重新索引
Pandas DataFrame - 重新索引
Section titled “Pandas DataFrame - 重新索引”重新索引是将 DataFrame 或 Series 符合新的索引标签集的过程。它是数据对齐和处理(data alignment and manipulation)的基本操作。
通过重新索引实现的关键功能包括:
- 按照新的索引顺序对现有数据进行重新排序(reordering)。
- 为新索引中存在但原始对象中不存在的标签插入缺失值标记(missing value markers) (
NaN)。 - 丢弃原始对象中存在但新索引中不存在的标签对应的数据。
主要方法是 .reindex()。
示例:基本重新索引
Section titled “示例:基本重新索引”让我们创建一个 DataFrame,然后对其行和列进行重新索引。
import pandas as pdimport numpy as np
N = 5 # Using a smaller N for brevity
df = pd.DataFrame({ 'A': pd.date_range(start='2023-01-01', periods=N, freq='D'), 'x': np.linspace(0, stop=N - 1, num=N), 'y': np.random.rand(N), 'C': np.random.choice(['Low', 'Medium', 'High'], N).tolist(), 'D': np.random.normal(100, 10, size=(N)).tolist()})
print("Original DataFrame:")print(df)
# Reindex the DataFrame with a new index and new columns# New index includes existing (0, 2) and non-existing (5) labels# New columns include existing ('A', 'C') and non-existing ('B') labelsdf_reindexed = df.reindex(index=[0, 2, 5], columns=['A', 'C', 'B'])
print("\nReindexed DataFrame:")print(df_reindexed)输出 (随机值可能不同):
Original DataFrame: A x y C D0 2023-01-01 0.0 0.123456 Low 95.1234561 2023-01-02 1.0 0.654321 Medium 110.9876542 2023-01-03 2.0 0.987654 High 105.4567893 2023-01-04 3.0 0.321098 Low 89.1234564 2023-01-05 4.0 0.789012 Medium 101.567890
Reindexed DataFrame: A C B0 2023-01-01 Low NaN2 2023-01-03 High NaN5 NaT NaN NaN注意看:
- 索引标签为 0 和 2 的行被保留。
- 索引标签为 5 的行被添加,并填充了
NaN(或日期时间的NaT)。 - 列 ‘A’ 和 ‘C’ 被保留。
- 列 ‘B’ 被添加,并填充了
NaN。 - 原来的行 1, 3, 4 以及列 ‘x’, ‘y’, ‘D’ 被丢弃,因为它们不在新的索引/列列表中。
使用 reindex_like 与另一个对象对齐
Section titled “使用 reindex_like 与另一个对象对齐”有时,您希望重新索引一个对象,使其索引(index)和/或列(columns)与另一个现有对象匹配。reindex_like() 方法提供了一种便捷的方式来实现这一点。
示例:对齐 DataFrame
Section titled “示例:对齐 DataFrame”import pandas as pdimport numpy as np
# Create two DataFrames with different sizes and potentially different indexes/columnsdf1 = pd.DataFrame(np.random.randn(5, 3), index=list('acefh'), columns=['col1', 'col2', 'col3'])df2 = pd.DataFrame(np.random.randn(7, 3), index=list('abcdefg'), columns=['col1', 'col2', 'col3'])
print("DataFrame 1 (Original):")print(df1)
print("\nDataFrame 2 (Target Shape):")print(df2)
# Reindex df1 to match the index and columns of df2df1_aligned = df1.reindex_like(df2)print("\nDataFrame 1 Aligned with DataFrame 2:")print(df1_aligned)输出 (随机值可能不同):
DataFrame 1 (Original): col1 col2 col3a 0.123456 -0.987654 1.456789c -0.321098 1.098765 -0.765432e 0.543210 -0.109876 0.210987f -1.876543 0.765432 -0.987654h 0.112233 -0.445566 1.678901
DataFrame 2 (Target Shape): col1 col2 col3a -0.567890 1.234567 -0.112233b 0.876543 -0.345678 1.998877c -1.112233 0.556677 -0.223344d 0.445566 -1.778899 0.334455e -0.667788 0.112233 -1.445566f 1.889900 -0.556677 0.778899g -0.223344 1.334455 -0.889900
DataFrame 1 Aligned with DataFrame 2: col1 col2 col3a 0.123456 -0.987654 1.456789b NaN NaN NaNc -0.321098 1.098765 -0.765432d NaN NaN NaNe 0.543210 -0.109876 0.210987f -1.876543 0.765432 -0.987654g NaN NaN NaN注意:df1_aligned 现在与 df2 具有相同的索引(从 ‘a’ 到 ‘g’)和列。对于 df2 的索引中存在但 df1 原始数据中也有数据的标签 (a, c, e, f),这些数据被保留。对于 df2 的索引中存在但 df1 原始数据中没有数据的标签 (b, d, g),则插入了 NaN 值。df1 原始数据中索引标签不在 df2 中的行(例如 ‘h’)被丢弃。
在重新索引期间填充缺失值
Section titled “在重新索引期间填充缺失值”.reindex() 和 .reindex_like() 方法接受一个可选的 method 参数,用于填充重新索引过程中创建的空洞(NaN 值)。常用的填充方法包括:
method='pad'或method='ffill':前向填充 - 将最后一个有效观测值向前传播以填充空白。method='bfill'或method='backfill':后向填充 - 使用下一个有效观测值向后填充空白。method='nearest':使用最近的索引标签对应的值填充。
示例:前向填充 (ffill)
Section titled “示例:前向填充 (ffill)”import pandas as pdimport numpy as np
# DataFrame with fewer rowsdf_sparse = pd.DataFrame(np.random.randn(3, 3), index=[0, 3, 5], columns=['col1', 'col2', 'col3'])
# Target index with more rowstarget_index = pd.Index(range(7))
print("Original Sparse DataFrame:")print(df_sparse)
# Reindex and fill NaN using forward filldf_filled_ffill = df_sparse.reindex(target_index, method='ffill')
print("\nDataFrame Reindexed with Forward Fill:")print(df_filled_ffill)输出 (随机值可能不同):
Original Sparse DataFrame: col1 col2 col30 0.123456 -0.987654 1.4567893 -0.321098 1.098765 -0.7654325 0.543210 -0.109876 0.210987
DataFrame Reindexed with Forward Fill: col1 col2 col30 0.123456 -0.987654 1.456789 # Original1 0.123456 -0.987654 1.456789 # Filled from index 02 0.123456 -0.987654 1.456789 # Filled from index 03 -0.321098 1.098765 -0.765432 # Original4 -0.321098 1.098765 -0.765432 # Filled from index 35 0.543210 -0.109876 0.210987 # Original6 0.543210 -0.109876 0.210987 # Filled from index 5注意看,索引 0 的值用于填充索引 1 和 2,索引 3 的值填充索引 4,索引 5 的值填充索引 6。
限制填充传播
Section titled “限制填充传播”limit 参数可以控制在重新索引期间,ffill 或 bfill 操作填充连续 NaN 值的数量。
示例:带限制的前向填充
Section titled “示例:带限制的前向填充”import pandas as pdimport numpy as np
# DataFrame with fewer rowsdf_sparse = pd.DataFrame(np.random.randn(3, 3), index=[0, 4, 7], columns=['col1', 'col2', 'col3'])
# Target index with more rowstarget_index = pd.Index(range(9))
print("Original Sparse DataFrame:")print(df_sparse)
# Reindex and forward fill, but limit filling to 2 consecutive NaNsdf_filled_limit = df_sparse.reindex(target_index, method='ffill', limit=2)
print("\nDataFrame Reindexed with Forward Fill (limit=2):")print(df_filled_limit)输出 (随机值可能不同):
Original Sparse DataFrame: col1 col2 col30 0.123456 -0.987654 1.4567894 -0.321098 1.098765 -0.7654327 0.543210 -0.109876 0.210987
DataFrame Reindexed with Forward Fill (limit=2): col1 col2 col30 0.123456 -0.987654 1.456789 # Original1 0.123456 -0.987654 1.456789 # Filled (1st)2 0.123456 -0.987654 1.456789 # Filled (2nd)3 NaN NaN NaN # Not filled (limit reached)4 -0.321098 1.098765 -0.765432 # Original5 -0.321098 1.098765 -0.765432 # Filled (1st)6 -0.321098 1.098765 -0.765432 # Filled (2nd)7 0.543210 -0.109876 0.210987 # Original8 0.543210 -0.109876 0.210987 # Filled (1st)注意,索引 3 仍然是 NaN,因为从索引 0 开始的填充被限制为 2 步(索引 1 和 2)。
重命名索引标签和列名
Section titled “重命名索引标签和列名”rename() 方法允许您基于映射(例如字典)或函数重新标记索引条目(index entries)或列名(column names)。这与重新索引不同,因为它保留了与原始标签关联的数据,并赋予其新名称,而不是基于标签值进行对齐。
让我们重命名一些列和索引标签:
import pandas as pdimport numpy as np
df = pd.DataFrame(np.random.randn(6, 3), index=range(6), columns=['col1', 'col2', 'col3'])print("Original DataFrame:")print(df)
renamed_df = df.rename( columns={'col1': 'Column_A', 'col2': 'Column_B'}, index={0: 'Row_Zero', 1: 'Row_One', 2: 'Row_Two'})
print("\nDataFrame with Renamed Rows and Columns:")print(renamed_df)
# To modify the DataFrame in place:# df.rename(columns={'col1': 'C1'}, index={0: 'R0'}, inplace=True)# print("\nDataFrame after inplace rename:")# print(df)输出 (随机值可能不同):
Original DataFrame: col1 col2 col30 0.486791 0.105759 1.5401221 -0.990237 1.007885 -0.2178962 -0.483855 -1.645027 -1.1941133 -0.122316 0.566277 -0.3660284 -0.231524 -0.721172 -0.1120075 0.438810 0.000225 0.435479
DataFrame with Renamed Rows and Columns: Column_A Column_B col3Row_Zero 0.486791 0.105759 1.540122Row_One -0.990237 1.007885 -0.217896Row_Two -0.483855 -1.645027 -1.1941133 -0.122316 0.566277 -0.3660284 -0.231524 -0.721172 -0.1120075 0.438810 0.000225 0.435479默认情况下,rename() 返回一个新的 DataFrame,其中包含更改 (inplace=False)。将 inplace 设置为 True 可以直接修改原始 DataFrame(请谨慎使用)。