Python:搜索从 pandas 数据帧列表中删除重复项的方法?
Python: searching way to remove duplicates from list of pandas dataframes?
我有一些包含 pandas 数据帧的列表。他们是从中删除重复项的一种方法。这里有一些示例代码:
import pandas as pd
import numpy as np
if __name__ == '__main__':
data1 = {'row_1': [3, 2, 1, 0], 'row_2': ['a', 'b', 'c', 'd']}
df1 = pd.DataFrame.from_dict(data1, orient='index', columns=['A', 'B', 'C', 'D'])
data2 = {'col_1': [3, 2, 1, 0], 'col_2': ['a', 'b', 'c', 'd']}
df2 = pd.DataFrame.from_dict(data2)
df3 = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
columns=['a', 'b', 'c'])
data = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)],
dtype=[("a", "i4"), ("b", "i4"), ("c", "i4")])
df4 = pd.DataFrame(data, columns=['c', 'a'])
l_input = [df1, df2, df1, df3, df4, df4, df1, df3]
# l_aim = [df1, df2, df3, df4]
应删除示例中的输入列表 l_input,结果应为 l_aim。
尝试 df.equals()
:
out = []
while l_input:
d = l_input.pop()
if any(d.equals(df) for df in l_input):
continue
out.append(d)
print(*out[::-1], sep="\n\n")
打印:
A B C D
row_1 3 2 1 0
row_2 a b c d
col_1 col_2
0 3 a
1 2 b
2 1 c
3 0 d
a b c
0 1 2 3
1 4 5 6
2 7 8 9
c a
0 3 1
1 6 4
2 9 7
如果这些实际上是相同的对象(如您的示例所示),那么您可以使用它们的 id
s:
out = list(dict((id(df), df) for df in l_input).values())
如果没有,您可以使用 equals
:
输出:
[ A B C D
row_1 3 2 1 0
row_2 a b c d,
col_1 col_2
0 3 a
1 2 b
2 1 c
3 0 d,
a b c
0 1 2 3
1 4 5 6
2 7 8 9,
c a
0 3 1
1 6 4
2 9 7]
在线性时间内找到重复项的一种有效方法是计算数据帧的哈希值。用pythonhash
函数是不行的,但是pandas里面有个辅助函数:pandas.util.hash_pandas_object
.
该函数计算每行的哈希值,因此您需要聚合为单个值。 sum
可以使用,但可能会导致冲突。在这里,我选择了所有哈希的串联。如果你有巨大的数据帧,这可能会消耗大量内存(在这种情况下,可能会散列哈希列表)。
更新。 hashes的hash似乎比较理想,见答案末尾的第二个选项。
hashes = [pd.util.hash_pandas_object(d).astype(str).str.cat(sep='-')
for d in l_input]
# identify duplicated per index
dups = pd.Series(hashes).duplicated()
输出:
0 False
1 False
2 True
3 False
4 False
5 True
6 True
7 True
dtype: bool
要过滤唯一数据帧:
out = [d for d,h in zip(l_input, dups) if h]
具有哈希的哈希的变体
我最初不确定计算散列列表的散列是否安全,但是this seems to be the case,所以下面的第二种方法应该是首选:
def df_hash(df):
s = pd.util.hash_pandas_object(df)
return hash(tuple(s))
hashes = [df_hash(d) for d in l_input]
dups = pd.Series(hashes).duplicated()
out = [d for d,h in zip(l_input, dups) if h]
我有一些包含 pandas 数据帧的列表。他们是从中删除重复项的一种方法。这里有一些示例代码:
import pandas as pd
import numpy as np
if __name__ == '__main__':
data1 = {'row_1': [3, 2, 1, 0], 'row_2': ['a', 'b', 'c', 'd']}
df1 = pd.DataFrame.from_dict(data1, orient='index', columns=['A', 'B', 'C', 'D'])
data2 = {'col_1': [3, 2, 1, 0], 'col_2': ['a', 'b', 'c', 'd']}
df2 = pd.DataFrame.from_dict(data2)
df3 = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
columns=['a', 'b', 'c'])
data = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)],
dtype=[("a", "i4"), ("b", "i4"), ("c", "i4")])
df4 = pd.DataFrame(data, columns=['c', 'a'])
l_input = [df1, df2, df1, df3, df4, df4, df1, df3]
# l_aim = [df1, df2, df3, df4]
应删除示例中的输入列表 l_input,结果应为 l_aim。
尝试 df.equals()
:
out = []
while l_input:
d = l_input.pop()
if any(d.equals(df) for df in l_input):
continue
out.append(d)
print(*out[::-1], sep="\n\n")
打印:
A B C D
row_1 3 2 1 0
row_2 a b c d
col_1 col_2
0 3 a
1 2 b
2 1 c
3 0 d
a b c
0 1 2 3
1 4 5 6
2 7 8 9
c a
0 3 1
1 6 4
2 9 7
如果这些实际上是相同的对象(如您的示例所示),那么您可以使用它们的 id
s:
out = list(dict((id(df), df) for df in l_input).values())
如果没有,您可以使用 equals
:
输出:
[ A B C D
row_1 3 2 1 0
row_2 a b c d,
col_1 col_2
0 3 a
1 2 b
2 1 c
3 0 d,
a b c
0 1 2 3
1 4 5 6
2 7 8 9,
c a
0 3 1
1 6 4
2 9 7]
在线性时间内找到重复项的一种有效方法是计算数据帧的哈希值。用pythonhash
函数是不行的,但是pandas里面有个辅助函数:pandas.util.hash_pandas_object
.
该函数计算每行的哈希值,因此您需要聚合为单个值。 sum
可以使用,但可能会导致冲突。在这里,我选择了所有哈希的串联。如果你有巨大的数据帧,这可能会消耗大量内存(在这种情况下,可能会散列哈希列表)。
更新。 hashes的hash似乎比较理想,见答案末尾的第二个选项。
hashes = [pd.util.hash_pandas_object(d).astype(str).str.cat(sep='-')
for d in l_input]
# identify duplicated per index
dups = pd.Series(hashes).duplicated()
输出:
0 False
1 False
2 True
3 False
4 False
5 True
6 True
7 True
dtype: bool
要过滤唯一数据帧:
out = [d for d,h in zip(l_input, dups) if h]
具有哈希的哈希的变体
我最初不确定计算散列列表的散列是否安全,但是this seems to be the case,所以下面的第二种方法应该是首选:
def df_hash(df):
s = pd.util.hash_pandas_object(df)
return hash(tuple(s))
hashes = [df_hash(d) for d in l_input]
dups = pd.Series(hashes).duplicated()
out = [d for d,h in zip(l_input, dups) if h]