【问题标题】:Python Pandas find cell next to a known cellPython Pandas 在已知单元格旁边找到单元格
【发布时间】:2021-03-24 11:32:39
【问题描述】:

我有一个数据框'df_img_pred'用于某些图像处理算法的预测结果

Value A Rate_A Value B Rate_B Value C Rate_C
Dog 0.9 Bird 0.2 Fish 0.1
Tiger 0.1 Falcon 0.8 Whale 0.25

对于每一行,我想选择每个最大值及其对应的值。所以输出应该是:

Value Rate
Dog 0.9
Falcon 0.8

我有一个使用df_img_pred[['Rate_A','Rate_B','Rate_C']].max(axis= 1)的最大值列
我怎样才能得到它的列是索引的-1的对应值。不使用循环的最佳做法是什么?

【问题讨论】:

  • 请修改数据框结构以便更好理解......
  • 您只是在寻找df.shift(-1)吗?
  • @GilseungAhn 我已经修复了样式格式
  • @noah 不... shift 只是移动整个列。或者我不能用它写。请分享您对使用它的想法

标签: python python-3.x pandas dataframe


【解决方案1】:

您已经计算出max_rates,但您可以使用idxmax 来获取它们的列名:

max_rates = df.filter(like='Rate').max(axis=1)
col_names = df.filter(like='Rate').idxmax(axis=1)

# 0    Rate_A
# 1    Rate_B
# dtype: object

那么如果你shiftdf,那些相同的col_names列现在将包含相应的标签:

max_values = df.shift(axis=1).apply(lambda row: row[col_names[row.name]], axis=1)

# 0       Dog
# 1    Falcon
# dtype: object

那么你可以使用max_valuesmax_rates 构建最终结果:

pd.DataFrame({'Value': max_values, 'Rates': max_rates})

#      Value   Rate
# 0      Dog    0.9
# 1   Falcon    0.8

【讨论】:

  • 感谢您的出色解释
【解决方案2】:

你可以试试这个代码:

max_colums = df.loc[:, df.dtypes == float].idxmax(axis=1)
max_labels = max_colums.apply(df.columns.get_loc) - 1

max_colums = iter(max_colums.values)
max_labels = iter(max_labels.values)

print(
    pd.DataFrame(
        df.apply(
            lambda x: {
                "Value": x[next(max_labels)],
                "Rate": x[next(max_colums)],
            },
            axis=1,
        ).tolist()
    )
)

打印:

    Value  Rate
0     Dog   0.9
1  Falcon   0.8

【讨论】:

  • 所以第一行max_colums = df.loc[:, df.dtypes == float].idxmax(axis=1) 将返回具有最大值的列名。第二行做什么?我有 NaN 值,所以它对我不起作用
  • @Karim 是的,它将返回具有最大值的列索引(在每一行中)。 max_labels 将返回标签列的索引(假设它们按照您的问题排序)。
【解决方案3】:

这段代码怎么样?

import pandas as pd
df = pd.DataFrame([["Dog", 0.9, "Bird", 0.2, "Fish", 0.1],
                 ["Tiger", 0.1, "Falcon", 0.8, "Whale", 0.25]],
                 columns = ["Value A", "Rate_A", "Value B", "Rate_B", "Value C", "Rate_C"])


val_df = df[['Value A', 'Value B', 'Value C']]
rate_df = df[['Rate_A', 'Rate_B', 'Rate_C']]

max_col_idx = rate_df.idxmax(axis = 1).replace({"Rate_A":0, "Rate_B":1, "Rate_C":2})
max_idx = [(i, max_col_idx.iloc[i]) for i in range(len(max_col_idx))]

val = [val_df.iloc[idx] for idx in max_idx]
rate = [rate_df.iloc[idx] for idx in max_idx]

result = pd.DataFrame({"Value":val, "rate":rate})

我认为循环对于这个问题是必不可少的......
无论如何,它通过 idxmax 为 rate_df 的每一行找到列索引以最大化值,并使用它们从 val_df 和 rate_df 中选择最大值。

【讨论】:

  • 我认为应该有更有效的方式在excel中使用匹配功能。
【解决方案4】:

假设您的列是有序的,您可以使用argmax 来获取速率列上每行最大值的位置。然后创建一个掩码来提取这个速率和相应的值

# mask
m = np.arange(len(df)), np.argmax(df.filter(like='Rate').to_numpy(), axis=1)

res = pd.DataFrame({'value':df.filter(like='Value').to_numpy()[m],
                    'rate':df.filter(like='Rate').to_numpy()[m]})
print(res)
    value  rate
0     Dog   0.9
1  Falcon   0.8

【讨论】:

  • 你能解释一下你的面具是如何工作的吗?
  • @Karim 所以np.arange(len(df)) 用于rw 编号,np.argmax(df.filter(like='Rate').to_numpy(), axis=1) 是每行Rate 列中最大值的位置。最后,你会得到类似于一对 (row, col) 列表的东西来提取每一行的好列。然后你分别在 value 和 rate 列上使用它