【问题标题】:"ValueError: Length of values does not match length of index" when trying to modify column values a pandas groupby尝试修改pandas groupby的列值时出现“ValueError:值的长度与索引的长度不匹配”
【发布时间】:2018-03-08 21:18:03
【问题描述】:

我有一个数据框:

       A         C         D
0    one  0.410599 -0.205158
1    one  0.144044  0.313068
2    one  0.333674 -0.742165
3  three  0.761038 -2.552990
4  three  1.494079  2.269755
5    two  1.454274 -0.854096
6    two  0.121675  0.653619
7    two  0.443863  0.864436

假设A 是锚列。我现在想在顶部显示每个组值一次

        A         C         D
0    one  0.410599 -0.205158
1         0.144044  0.313068
2         0.333674 -0.742165
3  three  0.761038 -2.552990
4         1.494079  2.269755
5    two  1.454274 -0.854096
6         0.121675  0.653619
7         0.443863  0.864436

这是我想出的:

df['A'] = df.groupby('A', as_index=False)['A']\
        .apply(lambda x: x.str.replace('.*', '').set_value(0, x.values[0])).values

我的策略是进行 groupby,然后将所有值设置为除第一个以外的空字符串。这似乎不起作用,因为我得到:

ValueError: Length of values does not match length of index

这意味着我得到的输出不正确。欢迎任何想法/建议/改进。

我应该补充一点,我正在尝试概括一个解决方案,该解决方案可以在每个组的顶部或底部或中间挑选出值,所以我会更倾向于帮助我做到这一点的解决方案(为了理解,上面的示例显示了如何仅在每个组的顶部挑选出值,但是,我想概括一个解决方案,允许我在底部或中间挑选出它们)。

【问题讨论】:

  • 其实这里数据是排序的,直接用df.loc[df.A == df.A.shift(), 'A'] = ''?
  • @Zero 您可以假设它是针对这种情况进行排序的。但是,我正在尝试概括一种解决方案,该解决方案可以在每个组的顶部或底部或中间挑选出一个值。对于这个问题,我刚刚问过如何在每个组的顶部单独列出它。如果我自己无法弄清楚,我会就此提出一个单独的问题。
  • 当你有偶数元素时你会如何处理middle的情况?
  • @Zero 任何一方都可以——只要它在中间或接近中间。
  • @Zero 没问题。我可以接受不同的方法。我想知道它是否可以,因为例如,在我的代码中,可以调整 .set_value(0, x.values[0]) 索引,以便可以将 0 更改为任何内容 - 例如 len(x) // 2 或类似的东西。

标签: python pandas dataframe group-by pandas-groupby


【解决方案1】:

由于值已排序,因此对第一个和最后一个情况使用duplicated 方法。


保持第一

In [4233]: df.loc[df.A.duplicated(keep='first'), 'A'] = ''

In [4234]: df
Out[4234]:
       A         C         D
0    one  0.410599 -0.205158
1         0.144044  0.313068
2         0.333674 -0.742165
3  three  0.761038 -2.552990
4         1.494079  2.269755
5    two  1.454274 -0.854096
6         0.121675  0.653619
7         0.443863  0.864436

保持最后

In [4236]: df.loc[df.A.duplicated(keep='last'), 'A'] = ''

In [4237]: df
Out[4237]:
       A         C         D
0         0.410599 -0.205158
1         0.144044  0.313068
2    one  0.333674 -0.742165
3         0.761038 -2.552990
4  three  1.494079  2.269755
5         1.454274 -0.854096
6         0.121675  0.653619
7    two  0.443863  0.864436

【讨论】:

    【解决方案2】:

    由于索引错误,您的方法不起作用。当您按“A”分组时,索引在分组数据中的表示方式也相同。由于set_value(0) 找不到正确的索引,它使用该索引创建一个新对象。这就是长度不匹配的原因。

    修复 1
    reset_index(drop=True)

    df['A'] = df.groupby('A')['A'].apply(lambda x: x.str.replace('.*', '')\
                          .reset_index(drop=True).set_value(0, x.values[0])).values
    df
    
          A         C         D
    0    one  0.410599 -0.205158
    1         0.144044  0.313068
    2         0.333674 -0.742165
    3  three  0.761038 -2.552990
    4         1.494079  2.269755
    5    two  1.454274 -0.854096
    6         0.121675  0.653619
    7         0.443863  0.864436
    

    修复 2
    set_value

    set_value 有一个名为takeable 的第三个参数,它决定了如何处理索引。默认情况下它是False,但将其设置为True 对我的情况有效。

    除了Zero's solutions之外,在其组的中心隔离值的解决方案如下:

    df.A = df.groupby('A'['A'].apply(lambda x: x.str.replace('.*', '')\
                               .set_value(len(x) // 2, x.values[0], True)).values 
    
    df
    
           A         C         D
    0         0.410599 -0.205158
    1    one  0.144044  0.313068
    2         0.333674 -0.742165
    3         0.761038 -2.552990
    4  three  1.494079  2.269755
    5         1.454274 -0.854096
    6    two  0.121675  0.653619
    7         0.443863  0.864436
    

    【讨论】:

      猜你喜欢
      • 2018-12-19
      • 1970-01-01
      • 2018-09-23
      • 2021-06-30
      • 1970-01-01
      • 1970-01-01
      • 2021-12-28
      • 2021-05-19
      • 2022-01-13
      相关资源
      最近更新 更多