删除已交换列值的重复行

时间:2017-09-04 12:01:27

标签: python pandas dataframe duplicates

非常感谢您阅读。

我有一个大约200,000行和46列的pandas数据框。其中23列以" _1"而另外23个结束于" _2"。例如:

forename_1   surname_1   area_1   forename_2   surname_2   area_2
    george       neil       g         jim         bob        k
    jim          bob        k         george      neil       g
    pete         keith      k         dan         joe        q
    dan          joe        q         pete        keith      k
    ben          steve      w         richard     ed         p
    charlie      david      s         graham      josh       l

我已使用drop_duplicates成功删除了重复项,但现在想要删除重复的行,但它们所在的组(1或2)已被反转。

也就是说,对于一行,我想将forename_1,surname_1和area_1中的组合值与forename_2,surname_2和area_2中所有其他行的组合值进行比较。

我希望使用的测试类型如下:

如果" forename_1 + surname_1 + area_1 + forename_2 + surname_2 + area_2" =" forename_2 + surname_2 + area_2 + forename_1 + surname_1 + area_1", 然后重复删除

我希望只保留x个重复项中的第一个重复行(例如,保持='第一个')。

为了帮助解释,上面有两种情况需要删除副本:

forename_1   surname_1   area_1   forename_2   surname_2   area_2
george       neil       g         jim         bob        k
jim          bob        k         george      neil       g



forename_1   surname_1   area_1   forename_2   surname_2   area_2    
pete         keith      k         dan         joe        q
dan          joe        q         pete        keith      k

george + neil + g + jim + bob + k = george + neil + g + jim + bob + k等......

在每种情况下,两个中的第二行都将被删除,这意味着我的预期输出将是:

forename_1   surname_1   area_1   forename_2   surname_2   area_2
    george       neil       g         jim         bob        k
    pete         keith      k         dan         joe        q
    ben          steve      w         richard     ed         p
    charlie      david      s         graham      josh       l

我在R中看到了一个解决这个问题的答案,但是还有一种方法可以在Python中完成吗?

Compare group of two columns and return index matches R

非常感谢。

3 个答案:

答案 0 :(得分:1)

使用:

WeekFields.ISO
df1 = pd.DataFrame(np.sort(df.values, axis=1), index=df.index).drop_duplicates()
print (df1)
         0      1       2        3      4     5
0      bob      g  george      jim      k  neil
2      dan    joe       k    keith   pete     q
4      ben     ed       p  richard  steve     w
5  charlie  david  graham     josh      l     s

df2 = df.loc[df1.index]
print (df2)
  forename_1 surname_1 area_1 forename_2 surname_2 area_2
0     george      neil      g        jim       bob      k
2       pete     keith      k        dan       joe      q
4        ben     steve      w    richard        ed      p
5    charlie     david      s     graham      josh      l

答案 1 :(得分:1)

我认为使用np.sort(df.values, axis=1)时存在问题。虽然它独立地排序每一行(好),但它不尊重值来自哪个列(坏)。换句话说,这两个假设行

forename_1   surname_1   area_1   forename_2   surname_2   area_2
    george        neil        g          jim         bob        k
    george        jim         k         neil         bob        g

将按相同方式排序

In [377]: np.sort(np.array([['george', 'neil', 'g', 'jim', 'bob', 'k'],
                            ['george', 'jim', 'k', 'neil', 'bob', 'g']]), axis=1)
   .....: Out[377]: 
array([['bob', 'g', 'george', 'jim', 'k', 'neil'],
       ['bob', 'g', 'george', 'jim', 'k', 'neil']],
      dtype='<U6')

尽管他们的(forename, surname, area)三胞胎不同。

为了处理这种可能性,我们可以使用jezrael's original stack/unstack approach,并将df.sort_values夹在中间:

import numpy as np
import pandas as pd
df = pd.DataFrame(
    {'area_1': ['g', 'k', 'k', 'k', 'q', 'w', 's'],
     'area_2': ['k', 'g', 'g', 'q', 'k', 'p', 'l'],
     'forename_1': ['george', 'george', 'jim', 'pete', 'dan', 'ben', 'charlie'],
     'forename_2': ['jim', 'neil', 'george', 'dan', 'pete', 'richard', 'graham'],
     'surname_1': ['neil', 'jim', 'bob', 'keith', 'joe', 'steve', 'david'],
     'surname_2': ['bob', 'bob', 'neil', 'joe', 'keith', 'ed', 'josh']})

def using_stack_sort_unstack(df):
    df = df.copy()
    df.columns = df.columns.str.split('_', expand=True)
    df2 = df.stack()
    df2 = df2.sort_values(by=['forename', 'surname', 'area'])
    colnum = (df2.groupby(level=0).cumcount()+1).astype(str)
    df2.index = pd.MultiIndex.from_arrays([df2.index.get_level_values(0), colnum])
    df2 = df2.unstack().drop_duplicates()
    df2.columns = df2.columns.map('_'.join)
    return df2

print(using_stack_sort_unstack(df))

产量

  area_1 area_2 forename_1 forename_2 surname_1 surname_2
0      g      k     george        jim      neil       bob
1      k      g     george       neil       jim       bob
3      q      k        dan       pete       joe     keith
5      w      p        ben    richard     steve        ed
6      s      l    charlie     graham     david      josh

stack / sort / unstack操作的目的:

    df2 = df.stack()
    df2 = df2.sort_values(by=['forename', 'surname', 'area'])
    colnum = (df2.groupby(level=0).cumcount()+1).astype(str)
    df2.index = pd.MultiIndex.from_arrays([df2.index.get_level_values(0), colnum])
    df2 = df2.unstack().drop_duplicates()

是对每行中的('forename', 'surname', 'area')三元组进行排序 个别。排序有助于drop_duplicates识别(和删除)行 我们想要考虑相同。

这显示了using_stack_sort_unstackusing_npsort之间的差异。 请注意using_npsort(df)返回4行 using_stack_sort_unstack(df)返回5行:

def using_npsort(df):
    df1 = pd.DataFrame(np.sort(df.values, axis=1), index=df.index).drop_duplicates()
    df2 = df.loc[df1.index]
    return df2
print(using_npsort(df))

#   area_1 area_2 forename_1 forename_2 surname_1 surname_2
# 0      g      k     george        jim      neil       bob
# 3      k      q       pete        dan     keith       joe
# 5      w      p        ben    richard     steve        ed
# 6      s      l    charlie     graham     david      josh

答案 2 :(得分:1)

我也有这个问题。我有一个数据帧,其中行可能有两列交换,Sample1Sample2。我的示例可能更健壮,但我想确定。

data = pd.DataFrame({  'Sample1': [ 'AT1', 'AT1', 'AT1', 'AT1', 'AT2', 'AT2', 'AT2', 'AT2', 'AT3', 'AT3', 'AT3', 'AT3', 'AT4', 'AT4', 'AT4', 'AT4', 'AT5', 'AT5', 'AT5', 'AT5'],  'Sample2': [ 'AT2', 'AT3', 'AT4', 'AT5', 'AT1', 'AT3', 'AT4', 'AT5', 'AT1', 'AT2', 'AT4', 'AT5', 'AT1', 'AT2', 'AT3', 'AT5', 'AT1', 'AT2', 'AT3', 'AT4'],  's1v': [ 53, 69, 44, 54, 27, 60, 11, 98, 16, 48, 50, 68, 89, 9, 20, 0, 14, 42, 1, 85], 's2v': [ 27, 16, 89, 14, 53, 48, 9, 42, 69, 60, 20, 1, 44, 11, 50, 85, 54, 98, 68, 0], 'v': [ 74, 0, 36, 87, 74, 87, 64, 64, 0, 87, 2, 54, 36, 64, 2, 51, 87, 64, 54, 51] })

# Add duplicate marker column 
data['duplicate'] = False

# Scan table for duplicate rows 
for index, row in data.iterrows():
    s1 = row['Sample1']
    s2 = row['Sample2']
    data_row = data.iloc[ index ]
    if data_row['duplicate'] == False:
        dup_row = data.loc[ (data['Sample1'] == s2) & (data['Sample2'] == s1) ]
        if not dup_row.empty:
            data.loc[ (data['Sample1'] == s2) & (data['Sample2'] == s1), 'duplicate' ] = True

# Subset data 
data = data.loc[ data['duplicate'] == False ]

我无法使用iterrows()中的行,因为它不包含数据框中的更新值,这就是为什么我有data_row ...