pandas 3 的 unique 结果没有 squeeze,怎样取唯一字符串
pandas 3.0.6 中字符串 unique 可返回 ArrowStringArray,旧的 squeeze 链式调用因此失败。明确零个、一个和多个唯一值的约定,再决定取标量还是转 NumPy。
旧代码写成 s.unique().squeeze(),升级后出现:
AttributeError: 'ArrowStringArray' object has no attribute 'squeeze'
字符串内容没有变,变化的是 unique() 返回的对象。pandas 3 默认字符串类型在安装了 PyArrow 时可使用 Arrow 存储,去重结果也可以是扩展数组,不能继续把它当作一定拥有全部 NumPy 方法的 ndarray。
这一表现有 pandas 3.0.6、PyArrow 19.0.1 的明确环境记录。截至 2026 年 10 月 21 日,不能把给扩展数组补齐 squeeze() 当作已发布的修复。
如果业务只允许一个值,直接检查数量
下面假设一组记录的地区必须唯一,示例中的列名和内容可按实际数据替换:
import pandas as pd
regions = pd.Series(["east", "east"])
values = regions.unique()
if len(values) != 1:
raise ValueError("expected exactly one region")
region = values[0]
这样不依赖 NumPy 的降维方法,也不会在零个或多个唯一值时偷偷把不同形状的结果传给下游。注意 squeeze() 对单元素 NumPy 数组的结果还可能是零维数组;直接取下标取得的是元素本身。下游若真的依赖零维数组,而不是字符串标量,需保留那项接口约定。
缺失值是否参与唯一性判断要先确定。unique() 会保留缺失值;如果允许忽略缺失,可以明确写成 regions.dropna().unique(),但全缺失时会得到零个值,应由前面的数量检查拒绝。不能为消掉错误顺手丢弃缺失地区,让不完整数据被当成完整数据。
确实需要 NumPy 接口时,显式转换
后续代码还要做 NumPy 的形状操作,可以从 Series 边界就转换:
values_array = regions.drop_duplicates().to_numpy()
collapsed = values_array.squeeze()
这里保留按首次出现顺序去重的含义,但转换成 NumPy 后不再携带原扩展数组的全部类型信息。缺失值的具体表示、带时区数据或其他扩展类型的转换成本,要按真实列类型核对;不能把这段代码机械应用到所有 dtype。
不要把 s.squeeze() 直接替换进去。原来的 s 可能有多行,只是各行内容相同;对原 Series 降维并没有完成去重。也不要为了一个调用,把整站的字符串推断关闭或所有列改成 object。
复查时至少包含同值多行、单行、多种值、空 Series,以及业务允许的缺失组合。完成标准是下游收到约定的标量或数组,而且不该通过的多值输入仍被拒绝;只看这一次不再出现 AttributeError,会漏掉返回形状变化。


