如何基于字符串型索引为Pandas DataFrame添加多列?
Pandas DataFrame添加自定义类属性列的问题解决
问题背景
现有以字符串为索引的Pandas DataFrame:
import pandas as pd # 创建DataFrame df = pd.DataFrame({'Date':['10/2/2011', '11/2/2011', '12/2/2011', '13/2/2011'], 'Event':['Music', 'Poetry', 'Theatre', 'Comedy'], 'Cost':[10000, 5000, 15000, 2000]}, index=['john','mike','alfred','jerry']) print(df)
自定义telbook类存储员工属性:
class telbook(): def __init__(self): self.data = {'john':'python','mike':'C','alfred':'excel','jerry':'python'} self.country = {'john':'spain','mike':'India','alfred':'germany','jerry':'themoon'} book = telbook()
尝试用以下代码添加列时,未报错但结果全为NaN:
df['lang'] = pd.Series(df.index).apply(lambda user_name: book.data[user_name]) df['country'] = pd.Series(df.index).apply(lambda user_name: book.country[user_name])
问题解答
1. 正确的实现方式
出现NaN的核心原因是:你创建的pd.Series(df.index)使用默认数字索引(0、1、2、3),而原DataFrame的索引是john、mike这类字符串,赋值时索引无法对齐,导致所有值变为NaN。
有两种简洁的修正方式:
方式一:直接用索引的map方法(推荐)
Index.map可直接接收字典,自动根据索引键匹配取值,无需编写lambda:
df['lang'] = df.index.map(book.data) df['country'] = df.index.map(book.country)
方式二:保持apply但指定Series索引
如果坚持用apply,需让新Series的索引与原DataFrame一致:
df['lang'] = pd.Series(df.index, index=df.index).apply(lambda x: book.data[x]) df['country'] = pd.Series(df.index, index=df.index).apply(lambda x: book.country[x])
2. 批量添加多列的便捷方法
如果需要从telbook中提取多个属性列,最便捷的方式是把所有要添加的属性整合成新DataFrame,再与原DataFrame合并:
方法一:一次性构建属性DataFrame后合并
# 整理需要的属性为字典,键作为列名 additional_data = { 'lang': book.data, 'country': book.country } # 构建与原df索引一致的属性DataFrame attr_df = pd.DataFrame(additional_data, index=df.index) # 合并到原DataFrame df = df.join(attr_df)
方法二:循环批量添加(适合属性较多的场景)
如果telbook中有多个属性需要提取,可通过循环批量处理:
# 定义要提取的属性名和对应列名的映射 attr_mapping = [ ('data', 'lang'), ('country', 'country') ] for attr_name, col_name in attr_mapping: # 获取telbook中的属性字典 attr_dict = getattr(book, attr_name) # 添加列 df[col_name] = df.index.map(attr_dict)
内容的提问来源于stack exchange,提问作者JFerro
相关产品推荐
相关产品推荐

