【问题标题】:Pandas is not creating extra (duplicated) index after groupby and nlargest if all the values are the same如果所有值都相同,Pandas 不会在 groupby 和 nlargest 之后创建额外(重复)索引
【发布时间】:2021-10-15 07:13:23
【问题描述】:

我正在尝试获取代表大多数分组行的列值。假设我有以下数据框。

df = pd.read_csv("test2.csv")
print(df)

     loc address  mod1  mod2  mod3
0      A   addr1     0     0     0
1      A   addr1     0     1     0
2      A   addr1     0     3     0
3      A   addr1     0     3     0
4      A   addr1     0     3     2
5      A   addr1     0     3     2
6      A   addr1     0     3     2
7      A   addr2     0     0     0
8      A   addr2     0     1     0
9      A   addr2     0     1     0
10     B   addr1     0     0     0
11     B   addr1     0     0     2
12     B   addr1     0     1     1
13     B   addr1     0     0     2
14     B   addr1     0     2     2
15     B   addr2     0     1     0
16     C   addr1     0     1     0
17     C   addr1     0     0     1

“A addr1”组最能代表“mod2”的值为3,“A addr2”组为1。 为此,我使用以下代码:

a = df.groupby(['loc','address'])['mod2'] \
  .value_counts() \
  .groupby(['loc','address']) \
  .nlargest(1) \
  .reset_index(level=[0,1],drop=True) \
  .rename_axis(['loc','address','mod2']) \
  .reset_index(name='counts')[['loc','address','mod2']]
print(a)

  loc address  mod2
0   A   addr1     3
1   A   addr2     1
2   B   addr1     0
3   B   addr2     1
4   C   addr1     0

但是,当所有组的列值相同时,此操作会失败并显示消息“ValueError:新名称的长度必须为 1,得到 3”。请参阅上面打印的第一个数据框中的“mod1”列。我使用了相同的代码,只是将“mod2”列更改为“mod1”。

c = df.groupby(['loc','address'])['mod1'] \
      .value_counts() \
      .groupby(['loc','address']) \
      .nlargest(1) \
      .reset_index(level=[0,1],drop=True) \
      .rename_axis(['loc','address','mod1']) \
      .reset_index(name='counts')[['loc','address','mod1']]
print(c)

失败发生在代码的“rename_axis”部分。 value_counts 的“Groupby”将“loc”和“address”添加为索引,nlargest 的“groupby”复制了“mod2”的这些索引。但是,“mod1”的 nlargest 的“groupby”不会复制相同的索引,因为第一个和第二个“groupby”的输出是相同的,因为该列的所有行的值都为零。 “reset_index” 删除了前两个级别,导致第一个示例具有“loc”、“address”和“mod2”列,而第二个示例只有“mod1”列。

有什么办法可以避免这种情况吗?或者有没有办法简化我想要实现的目标?

编辑:预期结果应该如下:

  loc address  mod1 
0   A   addr1     0
1   A   addr2     0
2   B   addr1     0
3   B   addr2     0
4   C   addr1     0

然后我会加入他们有以下输出:

  loc address  mod1 mod2 
0   A   addr1     0    3
1   A   addr2     0    1
2   B   addr1     0    0
3   B   addr2     0    1
4   C   addr1     0    0

【问题讨论】:

  • 请您更新一下您的问题的预期结果吗?
  • @Corralien 我更新了我的帖子。

标签: python pandas


【解决方案1】:

nlargest(1) 替换为 head(1) 并仅将您的索引保留为数据框:

对于mod1

>>> df.groupby(['loc','address'])['mod1'] \
      .value_counts() \
      .groupby(['loc','address']) \
      .head(1) \
      .index.to_frame() \
      .reset_index(drop=True)

  loc address  mod1
0   A   addr1     0
1   A   addr2     0
2   B   addr1     0
3   B   addr2     0
4   C   addr1     0

对于mod2

  loc address  mod2
0   A   addr1     3
1   A   addr2     1
2   B   addr1     0
3   B   addr2     1
4   C   addr1     0

对于mod3

  loc address  mod3
0   A   addr1     0
1   A   addr2     0
2   B   addr1     2
3   B   addr2     0
4   C   addr1     0

【讨论】:

  • 如果有适合您的需要,别忘了accept an answer
  • 我做到了。感谢您的链接@corralien
【解决方案2】:

试试:

new_df = df[['loc', 'address']].drop_duplicates()
for col in df.drop(['loc', 'address'], axis=1).columns:
    new_df = new_df.merge(df[['loc', 'address', col]].value_counts().reset_index().sort_values(col).drop_duplicates(['loc', 'address'], keep='last'))

我的pandas 版本在df 上没有value_counts 功能(它来自1.1.0)所以我是从我的脑海中做到的。否则,您需要将函数更改为更长的 groupbycount

【讨论】:

  • 感谢您的帮助。但是,它并没有产生我想要的结果。通过将它与 Corralien 的答案结合起来,我将更多地使用它。
  • @goober 是的。而不是.sort_values(col),它应该按在value_counts 中生成的series 的名称排序,而不是col。这是无法实际运行代码的缺点:)
猜你喜欢
  • 2017-10-19
  • 1970-01-01
  • 1970-01-01
  • 2017-03-16
  • 2021-04-15
  • 2014-11-15
  • 1970-01-01
  • 2015-12-08
相关资源
最近更新 更多