如何将DataFrame按code和date去重并将Tb列宽表化为Y/N格式?
问题描述
我有一份需要整理格式的DataFrame数据,需求如下:
- 对
code和date字段去重 - 将数据转换为宽表格式,把
Tb列的不同取值作为新列名 - 若对应
code和date出现在该Tb分组中则标记为Y,否则标记为N
原始数据:
code date Tb 88 20250831 Tb-A 49 20250817 Tb-A 67 20250819 Tb-B 808 20250804 Tb-B 25 20250804 Tb-B 67 20250819 Tb-C 808 20250804 Tb-C 25 20250804 Tb-C
目标格式:
code date Tb-A Tb-B Tb-C 88 20250831 Y N N 49 20250817 Y N N 67 20250819 N Y Y 808 20250804 N Y Y 25 20250804 N Y Y
我的思路是先对code和date去重,再将Tb列pivot wider为列名并赋值Y/N,但不确定具体实现方法。
解决方案
Python pandas 实现
不需要手动提前去重,用pivot_table或crosstab就能一步完成分组标记:
方法1:pivot_table
import pandas as pd # 构造原始数据 df = pd.DataFrame({ 'code': [88, 49, 67, 808, 25, 67, 808, 25], 'date': [20250831, 20250817, 20250819, 20250804, 20250804, 20250819, 20250804, 20250804], 'Tb': ['Tb-A', 'Tb-A', 'Tb-B', 'Tb-B', 'Tb-B', 'Tb-C', 'Tb-C', 'Tb-C'] }) # 生成宽表,存在则标记Y,否则填充N result = df.pivot_table( index=['code', 'date'], columns='Tb', aggfunc=lambda x: 'Y' if len(x) > 0 else 'N', fill_value='N' ).reset_index() # 调整列名(去除层级结构) result.columns = result.columns.get_level_values(0) print(result)
方法2:crosstab(更简洁)
import pandas as pd df = pd.DataFrame({ 'code': [88, 49, 67, 808, 25, 67, 808, 25], 'date': [20250831, 20250817, 20250819, 20250804, 20250804, 20250819, 20250804, 20250804], 'Tb': ['Tb-A', 'Tb-A', 'Tb-B', 'Tb-B', 'Tb-B', 'Tb-C', 'Tb-C', 'Tb-C'] }) result = pd.crosstab( index=[df['code'], df['date']], columns=df['Tb'] ).applymap(lambda x: 'Y' if x > 0 else 'N').reset_index() print(result)
R tidyverse 实现
你的思路方向是对的,不过可以用pivot_wider直接处理,无需手动去重:
library(tidyverse) # 构造原始数据 df <- tibble( code = c(88, 49, 67, 808, 25, 67, 808, 25), date = c(20250831, 20250817, 20250819, 20250804, 20250804, 20250819, 20250804, 20250804), Tb = c("Tb-A", "Tb-A", "Tb-B", "Tb-B", "Tb-B", "Tb-C", "Tb-C", "Tb-C") ) # 生成宽表:存在的行标记Y,缺失的填充N result <- df %>% mutate(flag = "Y") %>% pivot_wider( id_cols = c(code, date), names_from = Tb, values_from = flag, values_fill = list(flag = "N") ) print(result)
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

