按Name分组查找DataFrame各列连续相同值的起止索引
问题背景
给定如下Pandas DataFrame:
df = pd.DataFrame({'Name': ['Tesla','Tesla','Tesla','Toyota','Ford','Ford','Ford','BMW','BMW','BMW','Mercedes','Mercedes','Mercedes'], 'Type': ['Model X','Model X','Model X','Corolla','Bronco','Bronco','Mustang','3 Series','-','-','Alpha','Alpha','S-Class'], 'Year': [2015, 2015, 2015, 2017, 2018, 2018, 2020, 2015, 2015, 2017, 2018, 2018, 2020], 'Price': [85000, 90000, 95000, 20000, 35000, 35000, 45000, 40000, 40000, 65000, 50000, 50000, 75000], 'Color': ['White','White','White','Red','Blue','Blue','Yellow','Silver','Silver','Black','White','White','Black'] })
数据展示如下:
Name Type Year Price Color 0 Tesla Model X 2015 85000 White 1 Tesla Model X 2015 90000 White 2 Tesla Model X 2015 95000 White 3 Toyota Corolla 2017 20000 Red 4 Ford Bronco 2018 35000 Blue 5 Ford Bronco 2018 35000 Blue 6 Ford Mustang 2020 45000 Yellow 7 BMW 3 Series 2015 40000 Silver 8 BMW - 2015 40000 Silver 9 BMW - 2017 65000 Black 10 Mercedes Alpha 2018 50000 White 11 Mercedes Alpha 2018 50000 White 12 Mercedes S-Class 2020 75000 Black
需求说明
需按Name列分组,为其他每一列查找连续相同值对应的start index(起始索引)和end index(结束索引),将结果存储为{起始索引:结束索引}的字典。示例:
Tesla分组中,Type列的Model X连续出现,对应字典项为0:2;Color列中Blue连续出现在索引4-5,对应字典项为4:5;Year列中2015在Tesla分组连续出现,对应字典项为0:2。
预期输出如下:Name:
{0: 2, 3: 3, 4: 6, 7: 9, 10: 12}
Type:
{0: 2, 3: 3, 4: 5, 6: 6, 7: 7, 8: 9, 10: 11, 12: 12}
Year:
{0: 2, 3: 3, 4: 5, 6: 6, 7: 8, 9: 9, 10: 11, 12: 12}
Price:
{0: 0, 1: 1, 2: 2, 3: 3, 4: 5, 6: 6, 7: 8, 9: 9, 10: 11, 12: 12}
Color:
{0: 2, 3: 3, 4: 5, 6: 6, 7: 8, 9: 9, 10: 11, 12:12}
尝试的代码
def find_indices(df, column): df1 = df.index.to_series().groupby(df[column]).agg(['first', 'last']).reset_index() df1 = df1.sort_values("first").reset_index() first_last_rows = df1.set_index('first')['last'].to_dict() print(column + ":") print(first_last_rows)
遇到的问题
运行上述代码后,Year和Color列的输出结果不符合预期,结束索引跨了不同的Name分组,没有正确识别同一Name分组内的连续相同值:
Year: {0: 8, 3: 9, 4: 11, 6: 12} Color: {0: 11, 3: 3, 4: 5, 6: 6, 7: 8, 9: 12}
需要修正代码,实现按Name分组查找各列连续相同值的起止索引。
解决方案
核心思路是先按Name分组,再在每个分组内识别连续相同值的块,具体实现如下:
import pandas as pd def find_indices(df, column): # 生成连续相同值的分组标识:同一Name内,值变化或Name变化时递增 df['group_id'] = (df[column] != df[column].shift()) | (df['Name'] != df['Name'].shift()) df['group_id'] = df['group_id'].cumsum() # 按group_id分组,获取每个组的首尾索引 result_df = df.groupby('group_id')['index'].agg(['first', 'last']) # 转换为有序字典 result_dict = dict(sorted(result_df.set_index('first')['last'].to_dict().items())) print(f"{column}:") print(result_dict) # 保留原始索引到单独列 df['index'] = df.index # 遍历所有列生成结果 for col in df.columns.drop('index'): find_indices(df, col)
代码说明
group_id生成:通过判断当前行的目标列值或Name是否与前一行不同,生成布尔值后累加,确保同一Name内的连续相同值属于同一个分组;- 按
group_id分组后直接取首尾索引,避免跨Name分组的问题; - 最后对字典按起始索引排序,保证输出顺序符合预期。
运行上述代码后,输出结果将完全匹配预期。
内容的提问来源于stack exchange,提问作者Sudeep George
相关产品推荐
相关产品推荐

