我希望在数据框中尝试 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
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
图表: