如果有任何单个属性匹配,则用另一个替换Pandas的列值(确定两列是否具有公共属性)

2024-10-03 13:31:24 发布

您现在位置:Python中文网/ 问答频道 /正文

假设一个示例数据帧:

   Chemical   Compound     Name
0   Alcohol    Ethanol   Liquor
1     Hooch        NaN   Liquor
2   Cerveza    Ethanol      NaN
3   Bauxite  Aluminium Gibbsite
4  Feldspar  Aluminium      NaN

如果两行是相同的,替换或识别的有效方法是什么?(假设两行相同如果任何属性(列)匹配,而不一定全部匹配)

结果可能是:

^{pr2}$

或者:

   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

Tags: 数据name示例nancompoundchemicalalcoholethanol
2条回答

要标识至少具有一个匹配列的行:

>>> df.apply(lambda x: x.dropna().duplicated()).any(axis=1)
0    False
1     True
2     True
3    False
4     True
dtype: bool

在上面,第1、2和4行是“重复的”。第一排:白酒,第二排:乙醇,第四排:铝。在

不过,我不清楚你的填充逻辑。在

这是一个集合合并/连接组件/联合查找问题的伪装。在

如果我们任意决定将其视为一个连接组件问题,我们可以将框架中的每个单词想象为一个节点。A行基本上说那里的元素是等价的,或者换句话说,是可到达的:节点之间有边。为了确定同义词的集合,我们需要找到图的连接组件。在

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")

给了我

^{pr2}$

因为一旦我们做了带边的图(等价)

^{3}$

我们可以要求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函数,只需设置一点,或者使用现成的集合合并算法来查找组。例如,使用集合合并算法here,我们可以

In [240]: consolidate([set(row.dropna()) for _, row in df.iterrows()])
Out[240]: 
[{'Alcohol', 'Cerveza', 'Ethanol', 'Hooch', 'Liquor'},
 {'Aluminium', 'Bauxite', 'Feldspar'}]

我们又有了我们需要的团队。在

相关问题 更多 >