You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何拆解DataFrame中嵌套字典列表并提取指定字段?

解决方案

错误原因

TypeError: 'float' object is not iterable 是因为你的priceHistory列中存在非列表类型的值(比如空字符串、NaN,在pandas中NaN会被识别为float类型),当lambda尝试遍历这些非列表值时触发报错。

分步解决代码

1. 预处理priceHistory列

先统一列内数据类型,把所有非列表的值转换为空列表,避免遍历出错:

import pandas as pd

# 你的原始DataFrame
df = pd.DataFrame(
    [[19, [{'priceChangeRate': 0, 'date': '2015-05-29', 'source': 'Public Record', 'postingIsRental': False, 'time': 1432857600000, 'sellerAgent': None, 'showCountyLink': False, 'attributeSource': {'infoString2': 'Public Record', 'infoString3': None, 'infoString1': None}, 'pricePerSquareFoot': 275, 'buyerAgent': None, 'event': 'Sold', 'price': 877205}], ['Low flow commode', 'Low flow fixtures', 'Water-Smart Landscaping'],''],
     [89, [{'priceChangeRate': 0.090909090909091, 'date': '2023-07-14', 'source': 'Public Record', 'postingIsRental': False, 'time': 1689292800000, 'sellerAgent': {'name': 'seller1', 'photo': {'url': 'https://sellerphoto1.jpg'}, 'profileUrl': '/profile/sellerprofile1/'}, 'showCountyLink': False, 'attributeSource': {'infoString2': 'Public Record', 'infoString3': None, 'infoString1': None}, 'pricePerSquareFoot': 308, 'buyerAgent': {'name': 'buyer1', 'photo': {'url': 'https://buyerphoto1.jpg'}, 'profileUrl': '/profile/buyerprofile1/'}, 'event': 'Sold', 'price': 1200000}, {'priceChangeRate': 0, 'date': '2015-08-20', 'source': 'Public Record', 'postingIsRental': False, 'time': 1440028800000, 'sellerAgent': None, 'showCountyLink': False, 'attributeSource': {'infoString2': 'Public Record', 'infoString3': None, 'infoString1': None}, 'pricePerSquareFoot': 50, 'buyerAgent': None, 'event': 'Sold', 'price': 195000}],'', ['Windows', 'Insulation', 'HVAC', 'Appliances', 'Lighting']]],
    columns=['id', 'priceHistory', 'WaterConservation', 'EnergyEfficient'])

# 预处理priceHistory:非列表值转为空列表
df['priceHistory'] = df['priceHistory'].apply(lambda x: x if isinstance(x, list) else [])

2. 拆解priceHistory中的date和price

根据业务需求选择以下两种方式:

方式一:展开所有历史记录(多行)

把每行的多个价格历史拆分成单独的行,保留所有记录:

# 将priceHistory列表展开为多行
price_expanded = df.explode('priceHistory', ignore_index=True)
# 从字典中提取date和price字段
price_expanded[['date', 'price']] = price_expanded['priceHistory'].apply(
    lambda d: pd.Series([d.get('date'), d.get('price')]) if d else pd.Series([None, None])
)
# 可删除原priceHistory列
price_expanded = price_expanded.drop('priceHistory', axis=1)
print(price_expanded)

方式二:提取每行最新的价格记录(单行)

如果只需要每行的最新价格(按日期排序取最后一条):

def extract_latest_price(history_list):
    if not history_list:
        return pd.Series([None, None])
    # 按日期排序,取最后一条记录
    sorted_history = sorted(history_list, key=lambda x: x.get('date', ''))
    latest_record = sorted_history[-1]
    return pd.Series([latest_record.get('date'), latest_record.get('price')])

# 添加最新日期和价格列
df[['latest_date', 'latest_price']] = df['priceHistory'].apply(extract_latest_price)
print(df)

3. 处理WaterConservation和EnergyEfficient列

根据需求选择:

方式一:转成逗号分隔字符串

把列表格式的内容转为可读性更强的字符串:

df['WaterConservation'] = df['WaterConservation'].apply(
    lambda x: ', '.join(x) if isinstance(x, list) else str(x).strip()
)
df['EnergyEfficient'] = df['EnergyEfficient'].apply(
    lambda x: ', '.join(x) if isinstance(x, list) else str(x).strip()
)

方式二:展开为多行

把每个列表条目拆分成单独的行:

# 分别展开节水、节能列
water_expanded = df.explode('WaterConservation', ignore_index=True)
energy_expanded = df.explode('EnergyEfficient', ignore_index=True)

# 同时展开两个列(会产生笛卡尔积,需根据业务场景选择)
combined_expanded = df.explode('WaterConservation').explode('EnergyEfficient', ignore_index=True)

内容的提问来源于stack exchange,提问作者Kerry Harp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 19:05:22