在 python 数据框中执行 vlookup 类型链,标记完成的迭代次数并在另一个数据框中发布结果

问题描述 投票:0回答:1

我希望在数据框中尝试 vlookup 链,并将结果发布在新的数据框中。

实际的数据帧有很多列,但对于此任务,我只对 2 感兴趣。数据帧中放置的数据或元素不是随机的,而是全部链接在一起,因此 a 列中的值与 b 列相关。下面我的虚拟数据可能无法正确显示这一点,但也许我的输出可能有意义。

data = {'a': [111, 112, 113, 114, 115, 215, 214, 213, 212, 211],
        'b': [112, 113, 114, 115, 116, 214, 213, 212, 211, 210]}

通过上面的输出,我想首先检查 a 列中存在于 b 列中的每个元素是否是我的初始搜索开始。

例如,如果我们使用 115 作为示例(我知道它不是第一个元素,但无论第一个元素如何,我都希望每个元素重复此结果)

115在两列中都存在,在B列中搜索它,然后找到后,在a列中查看与b列中的115相同索引的值,即114,现在在b列中搜索114,一旦找到搜索a 列中找到的 114 的索引为 113,直到找不到更多为止。这是第一个完整的迭代循环,然后第二个迭代循环将是相同的,但对于 215。

新的 df 将如下所示:

new_df =  {'found': [112, 113, 114, 115, 214, 213, 212, 211],
        'iteration': [1, 1, 1, 1, 2, 2, 2, 2]}

如果可能的话,省略半循环,所以如果 114 是一个新的起点,它将导致 114、113 和 112,但由于它是 115 中更大链的子集,我想省略它。

示例代码如下:

matches = df[df['a'].isin(df['b'])]

current_value = [df.loc[matches.index, 'a']][0]


result_dict = {'a': [], 'Chain':[]}

iteration = 1

for iteration, start_value in enumerate(starting_values, start=1):
    current_value = start_value
    visited_values = set()
    #iteration += 1
    values_in_loop = []

    while True:
        result.append(current_value)
        #iteration_results.add(iteration, start_value)
        if current_value in df['b'].values and current_value not in visited_values:
            current_index = df.index[df['b'] == current_value][0]
            current_value = df['a'].iloc[current_index]
            visited_values.add(current_value)
            values_in_loop.append(current_value)

        else:
            break
        
    iteration += 1   
    
new_df = pd.DataFrame({'found': result[::], 'Chain': iteration})

new_df
python pandas dataframe iteration isin
1个回答
0
投票

这是一个图形问题,请使用

network
weakly_connected_components
,以及可选的
pandas.factorize
:

# pip install networkx
import networkx as nx

G = nx.from_pandas_edgelist(df, source='b', target='a', create_using=nx.DiGraph)

groups = {n: i for i, g in enumerate(nx.weakly_connected_components(G), start=1)
          for n in g}

m = df['a'].isin(df['b'])

out = pd.DataFrame({'found': df.loc[m, 'a'],
                    'iteration': df.loc[m, 'a'].map(groups)
                    })
# optional
# if you must ensure that the numbers are 1 -> n without missing ones
out['iteration'] = pd.factorize(out['iteration'])[0]+1

输出:

   found  iteration
1    112          1
2    113          1
3    114          1
4    115          1
6    214          2
7    213          2
8    212          2
9    211          2

图表:

© www.soinside.com 2019 - 2024. All rights reserved.