【问题标题】:how remove rows in a dataframe that the order of values are not important如何删除数据框中值顺序不重要的行
【发布时间】:2018-06-22 04:13:53
【问题描述】:

我有一个这样的数据框:

source   target   weight
     1       2         5
     2       1         5
     1       2         5
     1       2         7
     3       1         6
     1       1         6
     1       3         6

我的目标是删除重复的行,但源列和目标列的顺序并不重要。事实上,两列的顺序并不重要,它们应该被删除。在这种情况下,预期的结果是

source   target   weight
     1       2         5
     1       2         7
     3       1         6
     1       1         6

没有循环有什么办法吗?

【问题讨论】:

  • @VenkataGogu 这不是那个问题的重复。试试df = pd.DataFrame({'a': [1, 2, 3], 'b': [2, 1, 1], 'c': [1, 3, 2]})df = df.drop_duplicates(subset=['a', 'b'], keep=False)。所有 3 行仍然存在。题名具体,数据清晰; OP 希望删除重复值,其中值可以出现在列的子集中,但它们出现在哪一列并不重要
  • 实际上我想不出一种优雅的方式来做到这一点,而不会随着列数的增加而失控。好问题。
  • 其实重量(第三列)的值很重要。
  • 你刚刚更新了你的预期结果,你能解释一下发生了什么变化吗?

标签: python pandas dataframe


【解决方案1】:

使用frozensetduplicated

df[~df[['source', 'target']].apply(frozenset, 1).duplicated()]

   source  target  weight
0       1       2       5
3       3       1       6
4       1       1       6

如果要考虑无序的source/targetweight

df[~df[['weight']].assign(A=df[['source', 'target']].apply(frozenset, 1)).duplicated()]

   source  target  weight
0       1       2       5
3       1       2       7
4       3       1       6
5       1       1       6

但是,要明确地使用更具可读性的代码。

# Create series where values are frozensets and therefore hashable.
# With hashable things, we can determine duplicity.
# Note that I also set the index and name to set up for a convenient `join`
s = pd.Series(list(map(frozenset, zip(df.source, df.target))), df.index, name='mixed')

# Use `drop` to focus on just those columns leaving whatever else is there.
# This is more general and accommodates more than just a `weight` column.
mask = df.drop(['source', 'target'], axis=1).join(s).duplicated()

df[~mask]

   source  target  weight
0       1       2       5
3       1       2       7
4       3       1       6
5       1       1       6

【讨论】:

    【解决方案2】:

    应该很容易。

    data = [[1,2,5],
    [2,1,5],
    [1,2,5],
    [3,1,6],
    [1,1,6],
    [1,3,6],
    ]
    df = pd.DataFrame(data,columns=['source','target','weight'])
    

    您可以使用drop_duplicates 删除重复项

    df = df.drop_duplicates(keep=False)
    print(df)
    

    会导致:

          source  target  weight
    1       2       1       5
    3       3       1       6
    4       1       1       6
    5       1       3       6
    

    因为您想处理无序的源/目标问题。

    def pair(row):
        sorted_pair = sorted([row['source'],row['target']])
        row['source'] =  sorted_pair[0]
        row['target'] = sorted_pair[1]
        return row
    df = df.apply(pair,axis=1)
    

    然后你可以使用df.drop_duplicates()

       source  target  weight
    0       1       2       5
    3       1       2       7
    4       1       3       6
    5       1       1       6
    

    【讨论】:

    • 行号 3,5 仍然重复
    • ...我什至在问题下给了 cmets,为什么它不像你说的那么简单。您的输出甚至与 OP 的预期输出不匹配。
    • 我已经删除了我的反对票,但这现在默认为 python 速度
    • 是的,任何使用原生 python 类型而不是 numpy 类型和运算符的解决方案都会导致正常的 CPython 执行速度。 piRSquared 的解决方案也是如此。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-12
    • 2018-11-11
    • 2020-10-21
    • 2015-11-27
    • 1970-01-01
    • 1970-01-01
    • 2020-12-21
    相关资源
    最近更新 更多