python - 如果任何单个属性匹配,则将 Pandas 的列值替换为另一个(确定两列是否具有共同属性)
问题描述
假设一个示例数据框:
Chemical Compound Name
0 Alcohol Ethanol Liquor
1 Hooch NaN Liquor
2 Cerveza Ethanol NaN
3 Bauxite Aluminium Gibbsite
4 Feldspar Aluminium NaN
替换或识别两行是否相同的有效方法是什么?(假设如果任何属性(列)匹配并且不一定全部匹配,则两行相同)
结果可能是:
Chemical Compound Name
0 Alcohol Ethanol Liquor
1 Alcohol NaN Liquor
2 Alcohol Ethanol NaN
3 Bauxite Aluminium Gibbsite
4 Bauxite Aluminium NaN
或者:
Chemical Compound Name Identifier
0 Alcohol Ethanol Liquor Alcohol
1 Hooch NaN Liquor Alcohol
2 Cerveza Ethanol NaN Alcohol
3 Bauxite Aluminium Gibbsite Bauxite
4 Feldspar Aluminium NaN Bauxite
解决方案
这是一个变相的集合合并/连接组件/联合查找问题。
如果我们任意决定将其视为连通分量问题,我们可以将框架中的每个单词想象成一个节点。一行基本上表示那里的元素是等价的,或者换句话说,是可达的:节点之间有边。为了确定同义词集,我们需要找到图的连通分量。
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'}]
然后剩下的就是把这些变成数字并随意选择使用第一个化学条目作为每个组的名称。
我们可以通过使用 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'}]
我们再一次拥有了我们需要的小组。
推荐阅读
- java - Android Studio - UI 线程未使用异步任务更新
- uitableview - tableviewcell 中的 BehaviorRelay
- javascript - nodejs ORA-01461: 只能绑定 LONG 值以插入 LONG 列
- java - Java - 算法 - 显示序列的所有可能性
- java - JdbcTestUtils 和事务上下文测试
- debugging - 调试触发的 modsecurity 规则命中
- python - Python相关问题 - 用户输入日期/N00B/
- .htaccess - 如果uri是root,需要在htaccess中设置env
- php - PHP 注意:遇到格式不正确的数值 - 过时的代码?
- python - Pandas 分析 - KeyError:“请求的级别(var1)与索引名称(无)不匹配”