如何根据与 pandas 的列值相似度查找相关行
How to find related rows based on column value similarity with pandas
给定一个随机数据集,我需要找到与第一行相关的行。
|Row|Foo|Bar|Baz|Qux|
|---|---|---|---|---|
| 0 | A |A |A | A |
| 1 | B | B | B | B |
| 2 | C | C | C |D|
| 3 | D |A | D |D|
我应该得到相关行 0、2 和 3,因为 0['Bar'] == 3['Bar']
和 3['Qux'] == 2['Qux']
。
我可以只遍历列以获得相似性,但这会很慢且效率低下,如果有新的相似性,我还需要再次迭代。
我希望有人能给我指出正确的方向,比如我应该看哪个 pandas
概念,或者哪些函数可以帮助我解决这个检索交叉数据的问题。我什至需要使用 pandas
吗?
编辑:
按照@goodside 的建议提供解决方案。此解决方案将循环,直到找不到更多新的匹配索引。
table = [
['A', 'A', 'A', 'A'],
['B', 'B', 'B', 'B'],
['C', 'C', 'C', 'D'],
['D', 'A', 'D', 'D']
]
comparators = [0]
while True:
for idx_row, row in enumerate(table):
if idx_row in comparators:
continue
for idx_col, cell in enumerate(row):
for comparator in comparators:
if cell == table[comparator][idx_col]:
comparators.append(idx_row)
break
else:
continue
break
else:
continue
break
else:
break
for item in comparators:
print(table[item])
这是一道图形题。您可以使用 networkx
:
# get the list of connected nodes per column
def get_edges(s):
return df['Row'].groupby(s).agg(frozenset)
edges = set(df.apply(get_edges).stack())
edges = list(map(set, edges))
# [{2}, {2, 3}, {0, 3}, {3}, {1}, {0}]
from itertools import pairwise, chain
# pairwise is python ≥ 3.10, see the doc for a recipe for older versions
# create the graph
import networkx as nx
G = nx.from_edgelist(chain.from_iterable(pairwise(e) for e in edges))
G.add_nodes_from(set.union(*edges))
# get the connected components
list(nx.connected_components(G))
输出:[{0, 2, 3}, {1}]
注意。您可以在 .
中阅读有关创建图形的逻辑的更多信息
使用的输入:
df = pd.DataFrame({'Row': [0, 1, 2, 3],
'Foo': ['A', 'B', 'C', 'D'],
'Bar': ['A', 'B', 'C', 'A'],
'Baz': ['A', 'B', 'C', 'D'],
'Qux': ['A', 'B', 'D', 'D']})
给定一个随机数据集,我需要找到与第一行相关的行。
|Row|Foo|Bar|Baz|Qux|
|---|---|---|---|---|
| 0 | A |A |A | A |
| 1 | B | B | B | B |
| 2 | C | C | C |D|
| 3 | D |A | D |D|
我应该得到相关行 0、2 和 3,因为 0['Bar'] == 3['Bar']
和 3['Qux'] == 2['Qux']
。
我可以只遍历列以获得相似性,但这会很慢且效率低下,如果有新的相似性,我还需要再次迭代。
我希望有人能给我指出正确的方向,比如我应该看哪个 pandas
概念,或者哪些函数可以帮助我解决这个检索交叉数据的问题。我什至需要使用 pandas
吗?
编辑:
按照@goodside 的建议提供解决方案。此解决方案将循环,直到找不到更多新的匹配索引。
table = [
['A', 'A', 'A', 'A'],
['B', 'B', 'B', 'B'],
['C', 'C', 'C', 'D'],
['D', 'A', 'D', 'D']
]
comparators = [0]
while True:
for idx_row, row in enumerate(table):
if idx_row in comparators:
continue
for idx_col, cell in enumerate(row):
for comparator in comparators:
if cell == table[comparator][idx_col]:
comparators.append(idx_row)
break
else:
continue
break
else:
continue
break
else:
break
for item in comparators:
print(table[item])
这是一道图形题。您可以使用 networkx
:
# get the list of connected nodes per column
def get_edges(s):
return df['Row'].groupby(s).agg(frozenset)
edges = set(df.apply(get_edges).stack())
edges = list(map(set, edges))
# [{2}, {2, 3}, {0, 3}, {3}, {1}, {0}]
from itertools import pairwise, chain
# pairwise is python ≥ 3.10, see the doc for a recipe for older versions
# create the graph
import networkx as nx
G = nx.from_edgelist(chain.from_iterable(pairwise(e) for e in edges))
G.add_nodes_from(set.union(*edges))
# get the connected components
list(nx.connected_components(G))
输出:[{0, 2, 3}, {1}]
注意。您可以在
使用的输入:
df = pd.DataFrame({'Row': [0, 1, 2, 3],
'Foo': ['A', 'B', 'C', 'D'],
'Bar': ['A', 'B', 'C', 'A'],
'Baz': ['A', 'B', 'C', 'D'],
'Qux': ['A', 'B', 'D', 'D']})