Pandas 报错 Unalignable boolean Series provided as indexer 的解决方法
前言
最近本菜鸡在 批量处理 数据的时候出现了问题,场景是:批量获得数据,判断是否在指定 DataFrame 中,如果不在,则 存入,否则,读取 ,但是写好多线程后出现了问题,于是写下本篇文章来记录一下出现问题的原因及解决方法。
- 偷偷说一句:如果对我的文章满意的话可不可以给我
点个赞,点个收藏,点个关注,评论一下。 - 一定要
看到最后并且参加投票哦。 Let's do it !!!
改 bug
报错如下(因为已经解决了,不想,准确来说 不敢,再动我的代码,所以就不截图了):
Unalignable boolean Series provided as indexer (index of the boolean Series and of the indexed object do not match).
用 百度翻译 一下,也就是说:
作为索引器提供的不可对齐布尔序列(布尔序列的索引和索引对象的索引不匹配)。
我看了一下报错所在的行,这一行是:
if df[df['en' == kw].empty
我的本意是想判断 df 中是否有数据的 en 这一列的值等于给定的 kw,按理说是没有问题的,运行一次也是没有问题,可是开了多线程以后会有问题呢?
分析
让我们再回顾一下这个报错,说是 布尔序列的索引和索引对象的索引不匹配 。
第一步
首先,我们会有个疑问,这句话说的 布尔序列 哪里来的?
思考再三,我恍然大悟,应该是
df['en'] == kw
这句话来的。这句话会返回一个 和 df 行数一样,值都是 bool 的 Series ,然后 pandas 会取出这个 布尔序列 中值为 True 的多行数据。
第二步
然后,我们要知道它说的 和索引对象的索引不匹配 是什么意思。
索引对象 就是我们这个小例子中的 df 。也就是说,我们查找数据是查找的 df 中的数据,df 就是我们的 索引对象,既然是要从这里找数据,那我们就必须保证 df 的 索引 与上一步得到的 布尔序列 的索引一模一样(因为是根据值为 True 的数据对应的 索引 取数据),否则,我们是根本取不到对应索引的数据的。

如果说我们现在有个 DataFrame 是
name
0 张三
1 李四
3 王五
而我们要取数据的布尔序列是
0 False
2 True
3 False
那我们这时候就 根本不能取到数据,而且会报上述错误,因为 DataFrame 中就没有 索引为 2 的数据,你想让它给你造一个出来,那也不现实是不是?
解决
既然我们已经找到了问题所在,下面就是要解决这个问题了。
我的问题解决方案
先看一下我的问题,我的代码报错是因为:
开启多线程后,由于没有设置 锁,多个线程同时访问全局变量 df,导致其中一个线程 get 要进行 取数据 操作时,另一个线程 put 刚好在 get 线程执行完获得 布尔序列 语句与执行 查找数据 命令之间的时间对 df 进行了修改,导致 索引发生变化,因为写操作只有 增加,所以就是 get 线程获得 布尔序列 时 df 的行数小于 get 线程执行 查找操作 时 df 的行数,导致报错 。
可能我说的不是那么清晰,那就看一下下边的 时序图 。
那我的解决办法就是:执行 查找操作 时 上锁,同一时间只能进行 读操作 或 写操作。
所以修改代码为:
lock.acquire()
check_exists = df['en'] == kw
lock.release()
成功解决问题!!!
通用解决方案
有可能你的出错原因和我的不太一样,我的解决方案可能不太适用,所以我在这里给出一个通用的解决方案。
使用函数 reset_index 或者 reindex()。
-
reset_index(),使用方法见 文档。
一般来说,我们只需要看参数drop和inplace即可drop,是否删除原索引,如果要删除的话就设置为Trueinplace, 是否覆盖原DataFrame,如果要覆盖的话就设置为True
-
reindex(),使用方法见 文档。

keywords for axes,指定作为索引的轴。method,指定填补空白的方法,默认不填充空白。copy,是否复制为新对象。level,多重索引时,指定要更改索引的层级。fill_value,填补缺失值的值,默认为Nan。limit,向前或向后填充的最大连续元素的个数。tolerance,不精确匹配的原始标签和新标签之间的最大距离,要满足方程 a b s ( i n d e x [ i n d e x e r ] − t a r g e t ) < = t o l e r a n c e abs(index[indexer] - target) <= tolerance abs(index[indexer]−target)<=tolerance。
可以自行尝试。
结尾
有想要一起学习 python 的小伙伴可以 私信我 进群哦。
以上就是我要分享的内容,因为学识尚浅,会有不足,还请各位大佬指正。
有什么问题也可在评论区留言。

更多推荐

所有评论(0)