为熊猫设定差异

Rob*_*ith 38 python dataframe pandas

一个简单的熊猫问题:

是否有drop_duplicates()功能可以删除复制中涉及的每一行?

一个等效的问题如下:pandas对数据帧有不同的设置吗?

例如:

In [5]: df1 = pd.DataFrame({'col1':[1,2,3], 'col2':[2,3,4]})

In [6]: df2 = pd.DataFrame({'col1':[4,2,5], 'col2':[6,3,5]})

In [7]: df1
Out[7]: 
   col1  col2
0     1     2
1     2     3
2     3     4

In [8]: df2
Out[8]: 
   col1  col2
0     4     6
1     2     3
2     5     5
Run Code Online (Sandbox Code Playgroud)

所以也许df2.set_diff(df1)会产生这样的东西:

   col1  col2
0     4     6
2     5     5
Run Code Online (Sandbox Code Playgroud)

但是,我不想依赖索引,因为在我的情况下,我必须处理具有不同索引的数据帧.

顺便说一下,我最初考虑过当前drop_duplicates()方法的扩展,但现在我意识到使用集合论属性的第二种方法通常会更有用.但是,这两种方法都解决了我当前的问题

谢谢!

Joo*_*oop 40

有点复杂,但如果你想完全忽略索引数据.将数据帧的内容转换为包含列的元组集:

ds1 = set([tuple(line) for line in df1.values])
ds2 = set([tuple(line) for line in df2.values])
Run Code Online (Sandbox Code Playgroud)

此步骤也将删除数据帧中的任何重复项(忽略索引)

set([(1, 2), (3, 4), (2, 3)])   # ds1
Run Code Online (Sandbox Code Playgroud)

然后可以使用set方法来查找任何内容.例如找出差异:

ds1.difference(ds2)
Run Code Online (Sandbox Code Playgroud)

给出:set([(1,2),(3,4)])

如果需要,可以将其恢复为数据帧.注意必须将set转换为list 1st,因为set不能用于构造数据帧:

pd.DataFrame(list(ds1.difference(ds2)))
Run Code Online (Sandbox Code Playgroud)


aer*_*ite 26

from pandas import  DataFrame

df1 = DataFrame({'col1':[1,2,3], 'col2':[2,3,4]})
df2 = DataFrame({'col1':[4,2,5], 'col2':[6,3,5]})

print df2[~df2.isin(df1).all(1)]
print df2[(df2!=df1)].dropna(how='all')
print df2[~(df2==df1)].dropna(how='all')
Run Code Online (Sandbox Code Playgroud)

  • 我希望为我们这些试图跟进的人更多地解释这个答案。我认为所有三个答案都是相同的,但它们在结果中给出了不同的数据类型。我认为 ~ 否定了操作,但是 .all(1) 的目的是什么? (5认同)
  • 我相信这个解决方案只有在两个DataFrame上的索引相同时才有效.@Joop有一个没有这个条件的答案. (4认同)

rad*_*eam 25

这是保持索引的另一个答案,并且在两个数据帧中不需要相同的索引.(http://kechengpuzi.com/q/s37313691)

pd.concat([df2, df1, df1]).drop_duplicates(keep=False)
Run Code Online (Sandbox Code Playgroud)

它很快,结果是

   col1  col2
0     4     6
2     5     5
Run Code Online (Sandbox Code Playgroud)

  • 这很聪明。当然,它不具备集合论函数的灵活性。 (2认同)
  • 该答案意味着 df2 中存在任何重复的行(df2 已经位于行集中) (2认同)
  • @guilloptero:您可以通过在运行之前删除 df2 中的任何重复项来进行修改 (2认同)
  • @BryanP的建议有效:`pd.concat([df2.drop_duplicates(), df1, df1]).drop_duplicates(keep=False)` (2认同)

小智 5

有 3 种方法有效,但其中两种有一些缺陷。

方法一(哈希法):

它适用于我测试的所有情况。

df1.loc[:, "hash"] = df1.apply(lambda x: hash(tuple(x)), axis = 1)
df2.loc[:, "hash"] = df2.apply(lambda x: hash(tuple(x)), axis = 1)
df1 = df1.loc[~df1["hash"].isin(df2["hash"]), :]
Run Code Online (Sandbox Code Playgroud)

方法二(字典法):

如果 DataFrame 包含日期时间列,则会失败。

df1 = df1.loc[~df1.isin(df2.to_dict(orient="list")).all(axis=1), :]
Run Code Online (Sandbox Code Playgroud)

方法3(多索引方法):

我遇到过在 None 或 NaN 的列上失败的情况。

df1 = df1.loc[~df1.set_index(list(df1.columns)).index.isin(df2.set_index(list(df2.columns)).index)
Run Code Online (Sandbox Code Playgroud)


小智 5

Numpy 的 setdiff1d 可以工作并且可能更快。

对于每一列: np.setdiff1(df1.col1.values, df2.col1.values)

所以像这样:

setdf = pd.DataFrame({
    col: np.setdiff1d(getattr(df1, col).values, getattr(df2, col).values)
    for col in df1.columns
})
Run Code Online (Sandbox Code Playgroud)

numpy.setdiff1d 文档