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 行数一样,值都是 boolSeries ,然后 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 的行数,导致报错
可能我说的不是那么清晰,那就看一下下边的 时序图

get df put series = df['en'] == kw, (series.index=(1,...,n)) df.index=(1,...,n) df.loc[df.shape[0]+1]=data df.index=(1,...,n+1) df[series], (series.index=(1,...,n)) df.index=(1,...,n+1) get df put

那我的解决办法就是:执行 查找操作上锁,同一时间只能进行 读操作写操作
所以修改代码为:

lock.acquire()
check_exists = df['en'] == kw
lock.release()

成功解决问题!!!

通用解决方案

有可能你的出错原因和我的不太一样,我的解决方案可能不太适用,所以我在这里给出一个通用的解决方案。

使用函数 reset_index 或者 reindex()

  • reset_index(),使用方法见 文档

    在这里插入图片描述
    一般来说,我们只需要看参数 dropinplace 即可

    • drop ,是否删除原索引,如果要删除的话就设置为 True
    • inplace, 是否覆盖原 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 的小伙伴可以 私信我 进群哦。

以上就是我要分享的内容,因为学识尚浅,会有不足,还请各位大佬指正。
有什么问题也可在评论区留言。
在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐