1. The Data:

我在Pandas 数据框中有以下 struct :

import pandas as pd
df = pd.DataFrame([['A', 'NaN', 'A', 'NaN'],['B', 'A', 'B/A', 'A'], ['B1', 'B', 'B1/B/A', 'B/A'], 
                     ['B2', 'B', 'B2/B/A', 'B/A'], ['C', 'B1', 'C/B1/B/A', 'B1/B/A'], ['D', 'B1', 'D/B1/B/A', 'B1/B/A'], 
                     ['E', 'B2', 'E/B2/B/A', 'B2/B/A']], 
                    columns=['unit_id', 'group_id', 'new_unit_id', 'new_group_id'])

2. The issue and the goal:

我想用一个附加到父 struct 的值替换当前的unit_idgroup_id,基本上如下所示:

<unit_id> = <unit_id> + '/' + parent<unit_id>
and
<group_id> = parent<unit_id>

正如您在文件树 struct 或类似 struct 中看到的那样.

比如:

index unit_id group_id new_unit_id new_group_id
0 A NaN A NaN
1 B A B/A A
2 B1 B B1/B/A B/A
3 B2 B B2/B/A B/A
4 C B1 C/B1/B/A B1/B/A
5 D B1 D/B1/B/A B1/B/A
6 E B2 E/B2/B/A B2/B/A

3. Attempts and approach:

我曾try 过在不创建"新"列的情况下就地映射,但遇到了这样的问题:当父对象的unit_id更改时,它不会反映在其子对象的group_id中.

df['unit_id'] = df['unit_id'] + '/' + df['group_id']

所以我似乎需要逐行迭代,以便将前一行的更改考虑在内.比如:

df['unit_id'] = df.apply(lambda row : row['unit_id'].replace(str(row['unit_id']), str(row['unit_id'] + '/' + row['group_id'])), axis=1)

这会产生与上述相同(不准确)的值,但我认为使用正确的匿名(lambda)函数的df.apply更接近我需要的值.语法错误.

推荐答案

这可以用图论来解释.

这是你的图表:

enter image description here

您可以使用networkx来计算图形,并找到shortest_path:

import networkx as nx

# ensure real NaN
df = df.replace('NaN', np.nan)

G = nx.from_pandas_edgelist(df.dropna(subset='group_id'),
                            source='unit_id', target='group_id',
                            create_using=nx.DiGraph)

#get final item
last = list(nx.topological_sort(G))[-1]

# get simple paths
df['new_unit_id'] = ['/'.join(nx.shortest_path(G, s, last))
                      if not pd.isna(s) else float('nan')
                      for s in df['unit_id']]

df['new_group_id'] = df['new_unit_id'].str.extract(r'[^/]+/(.+)')

输出:

  unit_id group_id new_unit_id new_group_id
0       A      NaN           A          NaN
1       B        A         B/A            A
2      B1        B      B1/B/A          B/A
3      B2        B      B2/B/A          B/A
4       C       B1    C/B1/B/A       B1/B/A
5       D       B1    D/B1/B/A       B1/B/A
6       E       B2    E/B2/B/A       B2/B/A

Python相关问答推荐

在Admin中显示从ManyToMany通过模型的筛选结果

为什么我的sundaram筛这么低效

如何在Python请求中组合多个适配器?

如何在Gekko中使用分层条件约束

使用Python异步地持久跟踪用户输入

如何在Python 3.9.6和MacOS Sonoma 14.3.1下安装Pyregion

为什么Visual Studio Code说我的代码在使用Pandas concat函数后无法访问?

如何在微调Whisper模型时更改数据集?

如何定义一个将类型与接收该类型的参数的可调用进行映射的字典?

如何将参数名作为参数传入到函数中?

在PySpark中,可以从数组中获取任意数量的元素吗?

捕获脚本和退出代码的多行输出

抽象工厂模式与委托者模式组合时出现递归错误

Df.Drop_Duplates(),以极点表示?

在POLARS中,如何命名使用GROUP_BY和N_UNIQUE创建的列?

已超过url:/Forecast的最大重试次数.无法在Fastapi应用程序上建立新连接:[WinError 10061]

我很难用Python Pandas打开旧格式的XLS文件

如何在Python中删除对象

允许在枚举中使用一组特定的未定义值

如果没有强制转换Numy数组,则通过ctype将Numy数组传递给C函数会产生错误的结果