Pandas为何扁平化数组?如何遍历列表并筛选长度为2的元素?
问题描述
原始数据格式如下:
| index | date | temperature |
|---|---|---|
| 0 | 2021-6-1 | [14.1, 16.5] |
| 1 | 2021-6-10 | [19.0, 18.4] |
| 2 | 2021-6-11 | [24.4, 24.8] |
| 3 | 2021-6-12 | [25.4] |
该数据通过以下代码生成:
data = data.groupby(['date'])['temperature'].apply(list).reset_index()
尝试筛选temperature列中长度为2的元素,执行代码:
data = data[data['temperature'].apply(len) == 2]
却报错:object of type 'float' has no len()。用lambda打印元素时,发现输出的是单个数组元素而非列表。
补充信息:生成后的DataFrame中temperature列为object类型,df.to_dict('list')显示该列元素为array类型,执行df[df['temperature'].str.len().isna()]返回空DataFrame。
需要解决三个问题:
- Pandas为何会扁平化此类迭代?
- 如何遍历我的列表?
- 如何仅保留长度为2的列表?
解答
1. Pandas为何会扁平化此类迭代?
核心原因是原始temperature列的元素类型不统一,大概率混合了numpy数组和单个float值。当使用groupby.apply(list)时:
- 如果原始元素是numpy数组,
list()会直接将数组的元素展开成Python列表(比如np.array([14.1,16.5])会被转为[14.1,16.5]); - 如果原始元素是单个float值(可能是缺失值处理或数据导入时的异常),
list()无法将其转为列表,会直接保留为float类型。
而Pandas的object列允许混合存储多种类型,导致后续调用apply(len)时,遇到float类型的元素就会触发“没有len属性”的错误。
2. 如何遍历我的列表?
首先需要统一temperature列的元素类型,将所有元素转为标准Python列表:
# 将array或单个值统一转为列表,排除字符串类型(避免误转) data['temperature'] = data['temperature'].apply( lambda x: list(x) if hasattr(x, '__iter__') and not isinstance(x, (str, bytes)) else [x] )
完成类型统一后,即可正常遍历:
# 遍历每行的温度列表 for temp_list in data['temperature']: # 遍历列表中的每个温度值 for temp in temp_list: print(temp)
3. 如何仅保留长度为2的列表?
分两步处理:先统一元素类型,再筛选长度为2的行:
# 步骤1:统一转为列表 data['temperature'] = data['temperature'].apply( lambda x: list(x) if hasattr(x, '__iter__') and not isinstance(x, (str, bytes)) else [x] ) # 步骤2:筛选长度为2的行 data = data[data['temperature'].apply(len) == 2]
也可以合并为一行代码,直接在筛选时处理类型:
data = data[ data['temperature'].apply( lambda x: len(list(x)) if hasattr(x, '__iter__') and not isinstance(x, (str, bytes)) else len([x]) ) == 2 ]
内容的提问来源于stack exchange,提问作者LucioleMaléfique
相关产品推荐
相关产品推荐

