在 Pandas Dataframe 中获取具有非零列的前 11 行

Posted

技术标签:

【中文标题】在 Pandas Dataframe 中获取具有非零列的前 11 行【英文标题】:Get Top 11 rows with Non Zeros column in Pandas Dataframe 【发布时间】:2021-11-25 16:06:03 【问题描述】:

我有一个如下所示的 pandas 数据框。它有 11 列仅包含 0 和 1,以及带有一些值的列,最后一列是标识符。我在处理数据框时遇到了问题。

我有一种情况,我需要根据“值”列选择前 11 行。 (松约束)

但棘手的部分是我必须以这样一种方式选择行,这样我就不会在这 11 行中得到任何零列。 (硬约束)。

所以我需要根据值选择前 11 行,并确保所有列都不为零。每列中至少有一个值应为 1。

我正在寻找一些通用解决方案,因为 Value 列中的值会发生变化,但我的目标是根据值选择 11 行并确保非零列是必须的。

有什么想法吗?

a    b  c   d   e   f   g   h   i   j   k      values ID
0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.193744   1
0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 1.193744   2
0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.193744   3
0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 1.193744   4
0.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.193744   5
0.0 0.0 0.0 1.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 1.193744   6
0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.193744   7
0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.633150   8
0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.633150   9
0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.633150  10
0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.633150  11
0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.633150  12
0.0 0.0 1.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.033640  13
0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.033640  14
0.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.033640  15
1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.033640  16
0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.033640  17
1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.033640  18
0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.033640  19
1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.033640  20
0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.033640  21
0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.033640  22
0.0 1.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.033640  23
0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.033640  24
1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.033640  25
1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 -0.279495 26
1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 -3.013531 27
1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 -3.013531 28

【问题讨论】:

所以你想找到 a = 1 的最高值,b = 1 的最高值,......? 【参考方案1】:

使用自定义函数 - 先排序 values,然后选择前 11 列 DataFrame.iloc,通过DataFrame.astype 将浮点数转换为布尔值TrueFalses,因此如果至少有一个1 by DataFrame.rollingany,则可以测试每个N 块,因此将行移动@987654334 @ 由NaNs 填充,有必要用0 替换它们,转换为布尔值,如果所有行都有1DataFrame.all 进行可能的测试。

最后获取第一个True的索引,但如果所有Falses在Series.idxmax中返回0,所以添加if-else语句。

最后通过索引过滤top11:

def top_val_with_at_least_one_1(df, N):
    df = df.sort_values('values', ascending=False, ignore_index=True, kind='mergesort')

    m = (df.iloc[:, :11]
           .astype(bool)
           .rolling(N)
           .apply(lambda x: x.any())
           .fillna(0)
           .astype(bool)
           .all(axis=1))
    
    if m.any():
        idx = m.idxmax()
        return df.loc[idx-N+1:idx]
    else:
        return pd.DataFrame()


print (top_val_with_at_least_one_1(df, 11))
      a    b    c    d    e    f    g    h    i    j    k    values  ID
5   0.0  0.0  0.0  1.0  0.0  1.0  0.0  0.0  0.0  0.0  0.0  1.193744   6
6   0.0  0.0  0.0  1.0  1.0  0.0  0.0  0.0  0.0  0.0  0.0  1.193744   7
7   0.0  0.0  1.0  0.0  0.0  0.0  0.0  0.0  1.0  0.0  0.0  0.633150   8
8   0.0  0.0  1.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  1.0  0.633150   9
9   0.0  0.0  1.0  0.0  0.0  0.0  0.0  0.0  0.0  1.0  0.0  0.633150  10
10  0.0  0.0  1.0  0.0  0.0  0.0  1.0  0.0  0.0  0.0  0.0  0.633150  11
11  0.0  0.0  1.0  0.0  0.0  0.0  0.0  1.0  0.0  0.0  0.0  0.633150  12
12  0.0  0.0  1.0  0.0  1.0  0.0  0.0  0.0  0.0  0.0  0.0  0.033640  13
13  0.0  0.0  1.0  0.0  0.0  1.0  0.0  0.0  0.0  0.0  0.0  0.033640  14
14  0.0  1.0  0.0  0.0  0.0  0.0  0.0  1.0  0.0  0.0  0.0  0.033640  15
15  1.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  1.0  0.0  0.0  0.033640  16

【讨论】:

它获得前 11 行的最大值,但列 a 和 b 都是零。我们需要找到最上面的行,但它应该包含的列不应该为零 我尝试更改为 all 然后它给了我带有列标题的空数据框。可能是因为它试图根据价值观进入前 11 名。 我想让它们中的所有第 11 列都非零。所有列中至少有一个元素应为 1。在您的上述解决方案中,col a 和 b 为零列 是的,通过您的解决方案,它以最终结果的方式选择行。 a 列和 b 列完全为零。我们需要以这样一种方式获取行,即每列中至少有 1 个元素为 1,否则根据最高值可以全部为零。因此,如果顶部值返回 1 列完全为零的行。我们可以将它与另一个交换,但非零列约束是必须的 @Waqarulislam - 答案已编辑。【参考方案2】:

试试:

def get_desired_subset(top_rows):
    for i in range(len(df)):
        df_subset = df.loc[i:i+top_rows-1].reset_index(drop=True)
        if (df_subset>0).any().all():
            return df_subset

    print('No such subset found that satisfies all constraints.')
    return pd.DataFrame()

top_rows = 3
df = df[(df>0).any(axis=1)].sort_values(subset=['values'], ascending=False).reset_index(drop=True)
if len(df)>= top_rows:
    desired_df = get_desired_subset(3)
else:
    print('No such subset found that satisfies all constraints.')

【讨论】:

它获得前 11 行的最大值,但列 a 和 b 都是零。我们需要找到最上面的行,但它应该包含的列不应该为零@tlentali 它获得具有最大值的前 11 行,但列 a 和 b 都是零。我们需要找到最上面的行,但它应该包含的列不应该为零 如果我理解正确,您的意思是得到 11 行,其中至少有一个非零元素,此外,在这 11 行的子集中,一列作为一个整体不应为零。这是你想要的吗? 是的,使用您的解决方案,它会以最终结果的方式选择行。 a 列和 b 列完全为零。我们需要以这样一种方式获取行,即每列中至少有 1 个元素为 1,否则根据最高值可以全部为零。因此,如果顶部值返回 1 列完全为零的行。我们可以将其与另一个交换,但非零列约束是必须的。 我认为(df>1)这个检查应该在列级别,它在数据框级别,所以只要每行不为零,就可以考虑零列。但我不确定 已编辑,立即查看。

以上是关于在 Pandas Dataframe 中获取具有非零列的前 11 行的主要内容,如果未能解决你的问题,请参考以下文章

获取 Pandas DataFrame 列中字符串列表中的所有行 - 此模式具有匹配组

如何在 Pandas DataFrame 中一次获取多列的值计数?

为啥Pandas的DataFrame使用Series而非直接使用矩阵进行存储和数据操纵?

将具有相同列/索引的两个 pandas DataFrame 合并为一个 DataFrame

在 Pandas DataFrame 中定位第一个和最后一个非 NaN 值

如何使用 PANDAS 获取具有 NAN 值的列名并将这些列名存储在列表中? [复制]