Это скрытый вопрос о консолидации / связанных компонентах / объединении-поиске.
Если мы произвольно решим рассматривать его как проблему со связанными компонентами, мы можем представить каждое слово в вашем фрейме как узел.Строка в основном говорит, что элементы там эквивалентны или, другими словами, достижимы: между узлами есть ребра.Чтобы определить набор синонимов, нам нужно найти связанные компоненты графа.
import networkx as nx
G = nx.from_pandas_dataframe(df.stack().reset_index(), source='level_0', target=0)
codes = {v: i for i, vv in enumerate(nx.connected_components(G)) for v in vv}
df["Identifier"] = df["Chemical"].groupby(df["Chemical"].replace(codes)).transform("first")
дает мне
In [229]: df
Out[229]:
Chemical Compound Name Identifier
0 Alcohol Ethanol Liquor Alcohol
1 Hooch NaN Liquor Alcohol
2 Cerveza Ethanol NaN Alcohol
3 Bauxite Aluminium NaN Bauxite
4 Feldspar Aluminium NaN Bauxite
, потому что, как только мы сделаем граф с ребрами (эквивалентности)
In [233]: G.edges()
Out[233]:
[(0, 'Alcohol'),
(0, 'Ethanol'),
(0, 'Liquor'),
('Ethanol', 2),
('Liquor', 1),
(1, 'Hooch'),
(2, 'Cerveza'),
(3, 'Bauxite'),
(3, 'Aluminium'),
('Aluminium', 4),
(4, 'Feldspar')]
мы можем попросить networkx найти группы:
In [234]: list(nx.connected_components(G))
Out[234]:
[{0, 1, 2, 'Alcohol', 'Cerveza', 'Ethanol', 'Hooch', 'Liquor'},
{3, 4, 'Aluminium', 'Bauxite', 'Feldspar'}]
А затем остальные просто превращают их в числа и произвольно выбирают использование первой записи Chemical в качестве имени каждогоgroup.
Мы могли бы сделать то же самое, используя функцию scipy scipy.sparse.csgraph.connected_components, с чуть большей настройкой, или просто использовать готовый алгоритм объединения наборов для поиска групп.,Например, используя алгоритм консолидации множеств здесь , мы могли бы сделать
In [240]: consolidate([set(row.dropna()) for _, row in df.iterrows()])
Out[240]:
[{'Alcohol', 'Cerveza', 'Ethanol', 'Hooch', 'Liquor'},
{'Aluminium', 'Bauxite', 'Feldspar'}]
и снова у нас есть группы, которые нам нужны.