【问题标题】:How to analyze all duplicate entries in this Pandas DataFrame?如何分析此 Pandas DataFrame 中的所有重复条目?
【发布时间】:2016-02-25 19:09:37
【问题描述】:

我希望能够计算 Pandas DataFrame 中数据的描述性统计数据,但我只关心重复的条目。例如,假设我有由以下人员创建的 DataFrame:

import pandas as pd
data={'key1':[1,2,3,1,2,3,2,2],'key2':[2,2,1,2,2,4,2,2],'data':[5,6,2,6,1,6,2,8]}
frame=pd.DataFrame(data,columns=['key1','key2','data'])
print frame


     key1  key2  data
0     1     2     5
1     2     2     6
2     3     1     2
3     1     2     6
4     2     2     1
5     3     4     6
6     2     2     2
7     2     2     8

如您所见,第 0、1、3、4、6 和 7 行都是重复的(使用“key1”和“key2”。但是,如果我像这样索引这个 DataFrame:

frame[frame.duplicated(['key1','key2'])]

我明白了

   key1  key2  data
3     1     2     6
4     2     2     1
6     2     2     2
7     2     2     8

(即第 1 行和第 2 行不显示,因为它们没有被复制方法索引为 True)。

这是我的第一个问题。我的第二个问题涉及如何从这些信息中提取描述性统计数据。暂时忘记丢失的重复项,假设我想计算重复条目的 .min() 和 .max() (以便我可以获得一个范围)。我可以像这样在 groupby 对象上使用 groupby 和这些方法:

a.groupby(['key1','key2']).min()

这给了

           key1  key2  data
key1 key2                  
1    2        1     2     6
2    2        2     2     1

我想要的数据显然在这里,但我提取它的最佳方法是什么?如何索引生成的对象以获得我想要的(即 key1、key2、数据信息)?

【问题讨论】:

  • 注意:对于那些想知道为什么我在最后一个命令中有额外的 'key1' 和 'key2' 列的人,这是因为我使用的是 Pandas 0.07(这是 Ubuntu 存储库中可用的)。如果我升级到 Pandas 0.14,我不会再得到它(正如您在下面看到的 ajcr 和 Yoel 的答案)。

标签: python pandas dataframe


【解决方案1】:

编辑 Pandas 0.17 或更高版本:

由于自 Pandas 0.17 以来,duplicated() 方法的 take_last 参数是 deprecated 支持新的 keep 参数,请参阅 this answer 以了解正确的方法:

  • 使用keep=False 调用duplicated() 方法,即frame.duplicated(['key1', 'key2'], keep=False)

因此,为了提取此特定问题所需的数据,以下内容就足够了:

In [81]: frame[frame.duplicated(['key1', 'key2'], keep=False)].groupby(('key1', 'key2')).min()
Out[81]: 
           data
key1 key2      
1    2        5
2    2        1

[2 rows x 1 columns]

有趣的是,Pandas 0.17 中的这种变化可能部分归因于这个问题,如 this issue 中所述。


对于 Pandas 0.17 之前的版本:

我们可以使用duplicated() 方法的take_last 参数:

take_lastboolean,默认False

对于一组不同的重复行,将除最后一行之外的所有行标记为重复。默认为除第一行外的所有要标记的行。

如果我们将take_last 的值设置为True,我们会标记除最后一个重复行之外的所有行。将其与默认值False(标记除第一个重复行之外的所有行)结合使用,我们可以标记所有重复行:

In [76]: frame.duplicated(['key1', 'key2'])
Out[76]: 
0    False
1    False
2    False
3     True
4     True
5    False
6     True
7     True
dtype: bool

In [77]: frame.duplicated(['key1', 'key2'], take_last=True)
Out[77]: 
0     True
1     True
2    False
3    False
4     True
5    False
6     True
7    False
dtype: bool

In [78]: frame.duplicated(['key1', 'key2'], take_last=True) | frame.duplicated(['key1', 'key2'])
Out[78]: 
0     True
1     True
2    False
3     True
4     True
5    False
6     True
7     True
dtype: bool

In [79]: frame[frame.duplicated(['key1', 'key2'], take_last=True) | frame.duplicated(['key1', 'key2'])]
Out[79]: 
   key1  key2  data
0     1     2     5
1     2     2     6
3     1     2     6
4     2     2     1
6     2     2     2
7     2     2     8

[6 rows x 3 columns]

现在我们只需要使用groupbymin 方法,我相信输出是需要的格式:

In [81]: frame[frame.duplicated(['key1', 'key2'], take_last=True) | frame.duplicated(['key1', 'key2'])].groupby(('key1', 'key2')).min()
Out[81]: 
           data
key1 key2      
1    2        5
2    2        1

[2 rows x 1 columns]

【讨论】:

    【解决方案2】:

    要获取 Pandas 0.17 版中所有重复条目的列表,您只需在 duplicated 函数中设置 'keep = False'。

    frame[frame.duplicated(['key1','key2'],keep=False)]
    
        key1  key2  data
    0     1     2     5
    1     2     2     6
    3     1     2     6
    4     2     2     1
    6     2     2     2
    7     2     2     8
    

    【讨论】:

      【解决方案3】:

      这是在两列(即第 0、1、3、4、6、7 行)中返回 所有 个重复值的一种可能解决方案:

      >>> key1_dups = frame.key1[frame.key1.duplicated()].values
      >>> key2_dups = frame.key2[frame.key2.duplicated()].values
      >>> frame[frame.key1.isin(key1_dups) & frame.key2.isin(key2_dups)]
         key1  key2  data
      0     1     2     5
      1     2     2     6
      3     1     2     6
      4     2     2     1
      6     2     2     2
      7     2     2     8
      

      编辑:实际上,df.duplicated(take_last=True) | df.duplicated() 方法in @Yoel's answer 更简洁。)

      要查询groupby 操作的结果,可以使用loc。例如:

      >>> dups = frame[frame.key1.isin(key1_dups) & frame.key2.isin(key2_dups)]
      >>> grouped = dups.groupby(['key1','key2']).min()
      >>> grouped
                 data
      key1 key2      
      1    2        5
      2    2        1
      
      >>> grouped.loc[1, 2]
          data    5
      Name: (1, 2), dtype: int64
      

      或者,通过重置两个索引将grouped 变回“看起来正常”的DataFrame:

      >>> grouped.reset_index(level=0).reset_index(level=0)
         key2  key1  data
      0     2     1     5
      1     2     2     1
      

      【讨论】:

      • 感谢 ajcr 的回复。如果我想遍历最后一个对象中的条目,提取每个条目的 key1、key2 和数据值,那么正常的做法是什么?我只是在捡熊猫...
      • 其实我在这里找到了一个不错的解决方案:stackoverflow.com/questions/16476924/…
      • @gammapoint - 完全没问题。是的,iterrows() 将遍历 DataFrame 的行(尽管如果可能的话,通常最好避免以这种方式循环......它可能效率低下)。
      猜你喜欢
      • 1970-01-01
      • 2021-06-09
      • 2014-07-16
      • 1970-01-01
      • 2020-10-30
      • 2020-08-02
      • 1970-01-01
      • 2021-09-02
      • 2019-11-02
      相关资源
      最近更新 更多