【问题标题】:Keep only those columns in dataframe based on min value of each row根据每行的最小值仅保留数据框中的那些列
【发布时间】:2022-01-20 04:53:53
【问题描述】:

我有一个数据框

In = pd.DataFrame([["W",13,23,45,65], ["X",23,45,12,78], ["Y",12,34,56,89]],columns=["A","B","C","D","E"])

W 行的最小值为 13,X 行的最小值为 12,Y 行的最小值为 12。只保留所有行中具有最小值的列。

预期输出:

Out = pd.DataFrame([["W",13,45], ["X",23,12], ["Y",12,56]],columns=["A","B","D"])

怎么做?

【问题讨论】:

  • 如果连续有两列具有相同的最小值怎么办?你想保留两者还是任何一个?
  • 是的需要保留两列
  • 您可能希望将此详细信息添加到您的问题中。

标签: python python-3.x pandas dataframe


【解决方案1】:

您可以检查列是非数字还是包含最小值。

这种方法很有效,因为它首先计算每列的min,然后将每个最小值与全局最小值进行比较。

from pandas.api.types import is_numeric_dtype

# non-numeric
mask = In.apply(is_numeric_dtype)
# contains min
m = (m:=In.min()).eq(m[mask].min()) | ~mask
# If python < 3.8:
# m = In.min()
# m = m.eq(m[mask].min()) | ~mask

Out = In.loc[:,m]

输出:

   A   B   D
0  W  13  45
1  X  23  12
2  Y  12  56

【讨论】:

    【解决方案2】:

    在每列的最小值中找到最小值。将结果等同于 df。过滤任何具有最小值的列。在过滤发生之前将 A 设置为索引

    In.set_index('A', inplace=True)
    In.loc[:,(In==In.min().min()).any()].reset_index()
    

    如果您不想要多行代码,请使用以下代码

    In.set_index('A').loc[:,(In==(In.select_dtypes(exclude='object').min().min())).any()].reset_index()
    

    【讨论】:

    • 很好,我使用了类似的方法,但我认为更有效,因为它不需要根据最小值检查所有元素,并且更通用(不需要 set_index);)
    【解决方案3】:

    非常简单:声明 'A' 行索引;找到每一行中最小元素的列;消除重复的列;从原始数据框中选择幸存的列和“A”。

    columns_to_keep = In.set_index('A').idxmin(axis=1).unique().tolist()
    Out = In[['A'] + columns_to_keep]
    

    请注意,如果多列包含一行中的最小元素,则答案中仅包含第一列。

    【讨论】:

    • 虽然聪明,但这种方法是不正确的。如果最小值仅与前一列出现在同一行中,我将无法识别一列(idxmin 仅返回第一个匹配项),例如在 D 列中反转 12 和 56
    • @mozway 在您的示例中,B 列具有所有最小值,将被正确选择。从问题中不清楚如果有多个最小值该怎么办。此外,您的解决方案仅适用于 Python >= 3.8。
    • 我在之前的评论中提供了一个例子:在D列中反转12和56,D将无法被选中
    • @mozway 检查我更新的评论。
    • 我希望 OP 会澄清,但措辞方式我很确定应该选择 D。关于赋值表达式,这是一个实现细节,我加了注释;)
    猜你喜欢
    • 1970-01-01
    • 2021-08-01
    • 1970-01-01
    • 2016-04-13
    • 1970-01-01
    • 2017-01-14
    • 2021-12-27
    相关资源
    最近更新 更多