V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
Wolfsin
V2EX  ›  问与答

求解, Panda 比较操作会在一个循环执行第二遍时会报错

  •  
  •   Wolfsin · 2021-05-19 16:29:41 +08:00 · 697 次点击
    这是一个创建于 1286 天前的主题,其中的信息可能已经有所发展或是发生改变。
        for j in range(1, 6):
            TestSet = GroupList[j - 1]
            TrainSet = GroupList.copy()
            TrainSet.remove(TestSet)
    

    GroupList 里面存放的是结构相同的 Panda.DataFrame (仅数据不同),循环第一遍非常顺利,但是到了第二遍,会在 remove()操作这部报错:

    ValueError: Can only compare identically-labeled DataFrame objects

    因为用 PD 比较少,所以不太理解为什么会发生这种错误。 虽然可以改用 index 来 del(),但是还是想知道这样操作不行的理由。不知道有没有人遇到过。

    第 1 条附言  ·  2021-05-19 17:52:50 +08:00
    补一下 GroupList 的结构:
    GroupList= [DataFrame1,DataFrame2,DataFrame3,DataFrame4,DataFrame5]
    第 2 条附言  ·  2021-05-20 20:13:43 +08:00

    根据 rationa1cuzz 的实验,猜测是pd本身不支持从list[df1.df2]这种结构从比较df? 因为着急写脚本就没有继续深挖这个问题了,最后这个需求是用以下方式解决的。

    for j in range(1, 6):
      TestSet = GroupList[j - 1]
      TrainSet = GroupList.copy()
      TrainSet.pop(j)
    
    9 条回复    2021-05-20 22:00:59 +08:00
    rationa1cuzz
        1
    rationa1cuzz  
       2021-05-19 17:36:16 +08:00
    data=DataFrame.copy(deep=False)
    等价于
    data=DataFrame
    默认浅拷贝,你第一次给删了,肯定会出问题
    Wolfsin
        2
    Wolfsin  
    OP
       2021-05-19 17:49:50 +08:00
    @rationa1cuzz #1
    那个 GroupList 是一个 List,他的结构是

    List = [DataFrame1,DataFrame2,DataFrame3,DataFrame4,DataFrame5]

    list.copy(),虽然是浅拷贝,但是我断点下来的结果,第二次的 remove 前,list 跟第一次的 list 是一样的。

    另外如果对 list,做深拷贝( copy.deepcopy )那么在第一次 remove 时就会报:

    ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

    错误
    Wolfsin
        3
    Wolfsin  
    OP
       2021-05-19 17:58:38 +08:00
    @Wolfsin #2
    哦,另外我知道 list.copy(),对于 list 嵌套 list 这种情况,只能实现第一层的深拷贝,但是我这边的结构应该已经完成了深拷贝了。而且按照逻辑上来,即使是因为拷贝的问题,每次 remove()的对象,是上一轮中并没有被移除出去,所以应该也不会报错(就算是真有问题,应该也不是报 DataFrame 的错,应该是报 ValueError: list.remove(x): x not in list )
    toaruScar
        4
    toaruScar  
       2021-05-19 23:35:37 +08:00
    Functional programming 不香吗?都不用考虑深浅复制的问题

    for df in GroupList:
    print(list(filterfalse(lambda x: x.equals(df),GroupList)))
    toaruScar
        5
    toaruScar  
       2021-05-19 23:36:13 +08:00
    Xs0ul
        6
    Xs0ul  
       2021-05-20 02:54:17 +08:00   ❤️ 1
    看起来是要自己写 CV ?不如考虑用 sklearn 里的 split ?
    rationa1cuzz
        7
    rationa1cuzz  
       2021-05-20 10:33:51 +08:00   ❤️ 1
    不好意思之前没仔细看 ValueError: Can only compare identically-labeled DataFrame objects 看了一下这个报错应该是 GroupList 里的 TestSet 的 index 或者 columns 不一致导致的,第一遍顺利是因为行列一致,你可以打印看一下
    详见 /Library/Python/3.8/lib/python/site-packages/pandas/core/generic.py 1305 行
    另外 ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().这个报错估计是因为数据类型不一致导致的或者是 pandas 内部捕捉了直接 return,我本地 a=[df1,df2,df3] a.remove(df1)不报错 a.remove(df2)也会报错 ValueError,盲猜一个判断等于的时候报错 pandas 捕捉到了直接 return 了。具体你看看源码吧
    Wolfsin
        8
    Wolfsin  
    OP
       2021-05-20 20:07:52 +08:00
    @Xs0ul #6 谢谢推荐,不用 sklearn 的 split 是因为数据集已经分好 group 了,为了保证结果的可比较性,所以按照说明 4group 为 train,1group 为 test 。而且还要考虑排列组合的问题,所以还是打算手写了。
    @rationa1cuzz #7 感觉也是比较这边出的问题,不过最后偷懒用 index 移除了。而且这种方法好像还是速度还快一点。
    Xs0ul
        9
    Xs0ul  
       2021-05-20 22:00:59 +08:00   ❤️ 1
    好像回晚了,已经定好 group 的话也可以看看:
    https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GroupKFold.html#sklearn.model_selection.GroupKFold

    自己写的话,其实楼上用 filter 的可能比用 copy 和 pop 更好一点,或者直接更清晰一点写成类似:
    TrainSet = [g for i, g in enumerate(GroupList) if i != j]
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2809 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 15:08 · PVG 23:08 · LAX 07:08 · JFK 10:08
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.