如何高效地从多个数据框中获取单元格值以插入主数据框。

6

我有三个不同的数据框(一个主数据框和两个附加数据框)。我想要向主数据框添加一列,该列的元素是另外两个数据框中的不同单元格值。我使用主数据框的两列来确定需要从两个数据框中获取数据,并使用另外两个列作为索引以选择所选数据框中的特定单元格。


master_df = pd.DataFrame({
    'col1': ['M', 'F', 'F', 'M'],
    'col2': [0, 1, 2, 3],
    'col3': ['X', 'Z', 'Z', 'X'],
    'col4': [2021, 2022, 2023, 2024]
})

df1 = pd.DataFrame({
    2021: [.632, .214, .987, .555],
    2022: [.602, .232, .287, .552],
    2023: [.932, .209, .347, .725],
    2024: [.123, .234, .9873, .5005]
})

df2 = pd.DataFrame({
    2021: [.6123, .2214, .4987, .555],
    2022: [.6702, .232, .2897, .552],
    2023: [.9372, .2, .37, .725],
    2024: [.23, .24, .873, .005]
})


对于每一行的master_df,如果col1的值为'M'col3的值为'X',我要选择df1。如果col1的值为'F'col3的值为'Z',我要选择df2。一旦我选择了适当的DataFrame,我想使用master_dfcol2作为行索引,master_dfcol4作为列索引。最后,我将获得所选的单元格值,并将其放入新添加到master_df中的列中。
在这个例子中,master_df最终应该是这样的:
master_df = pd.DataFrame({
    'col1': ['M', 'F', 'F', 'M'],
    'col2': [0, 1, 2, 3],
    'col3': ['X', 'Z', 'Z', 'X'],
    'col4': [2021, 2022, 2023, 2024],
    'col5': [.632, .232, .37, .5005]
})

我尝试使用for循环遍历master_df,但由于我正在处理的DataFrame每个有数百万行数据,所以速度非常缓慢。有没有更高效的pandas解决方案?

2个回答

3

你的master_df只有master_df.col1master_df.col3两个值的组合。因此,简单的.lookupnp.where函数可以得到你想要的输出结果。

df1_val = df1.lookup(master_df.col2, master_df.col4)
df2_val = df2.lookup(master_df.col2, master_df.col4)
master_df['col5'] = np.where(master_df.col1.eq('M') & master_df.col3.eq('X'), df1_val, df2_val)

Out[595]:
  col1  col2 col3  col4    col5
0  M    0     X    2021  0.6320
1  F    1     Z    2022  0.2320
2  F    2     Z    2023  0.3700
3  M    3     X    2024  0.5005

注意:如果master_df.col1master_df.col3有超过两个值的组合,您只需要使用np.select而不是np.where


1
非常感谢,干净的解决方案。 - hbdch
@hbdch:很高兴我能帮到你 :) - Andy L.

2
"最初的回答":这里提供一种不使用for循环的解决方案,希望能对您有所帮助。
首先,我们将创建两个筛选器来确定要使用哪个数据框。
df1_filter = (master_df["col1"] == 'M') & (master_df["col3"] == 'X') 
df2_filter = (master_df["col1"] == 'F') & (master_df["col3"] == 'Z') 

其次,对于每个数据框,我们将使用适当的过滤器来获取感兴趣的值 对于 df1

最初的回答:

第二步,针对每个数据框,我们将使用相应的过滤器来获取所需的值。 对于df1:

row1_index = master_df[df1_filter]["col2"]
col1_index = master_df[df1_filter]["col4"]
df1_values_of_interest = df1.iloc[row1_index][col1_index]

最初的回答
对于df2
row2_index = master_df[df2_filter]["col2"]
col2_index = master_df[df2_filter]["col4"]
df2_values_of_interest = df2.iloc[row2_index][col2_index]

使用这种方法,感兴趣的值将位于对角线上,因此我们将尝试获取它们(每个值都有相应的索引),并将它们串联起来。最初的回答。
aa = pd.Series(np.diag(df1_values_of_interest), index=df1_values_of_interest.index)
bb = pd.Series(np.diag(df2_values_of_interest), index=df2_values_of_interest.index)
res = pd.concat([aa, bb])

最终,我们将把结果添加到主数据框中。
master_df['col5'] = res

我希望解决方案已经清晰明了,并且能够为您工作。如果您需要更多的澄清,请不要犹豫,随时问我。祝你好运!

最初的回答


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接