【问题标题】:How to delete rows based on threshold, but organized by another column?如何根据阈值删除行,但由另一列组织?
【发布时间】:2021-12-12 22:22:57
【问题描述】:

我正在尝试获取我的数据框并删除与另一行中的值相对应的每一行,具体取决于每个行类别是否包含超过阈值的值。虽然我觉得这应该是一个简单的“如果”条件语句,但我很困惑这是否真的像我想象的那么简单,或者这是否更复杂。我正在使用 python 和熊猫。我将通过下面的示例进行演示,以更好地传达此问题。

我有以下数据框:

Date              Category      Value
---------------------------------------
2015-06-02               1          2
2015-06-03               1          9
2015-06-04               1          2
2015-06-05               2          2
2015-06-06               2          8
2015-06-07               2         11
2015-06-08               2          2
2015-06-09               4          2
2015-06-10               4          5
2015-06-11               4         12
2015-06-12               4          2
2015-06-13               6          2
2015-06-14               6          8 
2015-06-15               6          2 
2015-06-16               8          2
2015-06-17               8          6
2015-06-18               8         10
2015-06-19               8          2 

如您所见,行按与“类别”列对应的特定 ID 进行分类。所以在这个例子中,有 5 个“类别”:“1”、“2”、“4”、“6”、“8”。只要类别保持不同,它们不会为每个类别增加 1 无关紧要。因此,您将看到一个模式,因为这是日期时间顺序数据,对于每个类别,该值从 2 开始,中间有一些值,无论有多少,并以 2 结束。所以每个类别都有“介于两者之间”的值值 2。我想要做的是获取数据框并删除两个值 2 之间的类别,对于该唯一类别,没有值 >= 10。如您所见,这意味着删除类别1(在 2 之间有 9),并删除类别 6(在 2 之间有 8)。当然,2 之间可以有任意数量的值,但其中至少一个必须 >= 10 所以我想生成以下数据框:

Date              Category      Value
---------------------------------------
2015-06-05               2          2
2015-06-06               2          8
2015-06-07               2         11
2015-06-08               2          2
2015-06-09               4          2
2015-06-10               4          5
2015-06-11               4         12
2015-06-12               4          2
2015-06-16               8          2
2015-06-17               8          6
2015-06-18               8         10
2015-06-19               8          2 

如何在 python 中做到这一点?虽然我想我会写一个条件语句,说“如果 df['Value'] 中的值

【问题讨论】:

  • 在您的输入数据中,所有类别都以3 开头,而不是描述中的2...
  • 对不起!我的意思是用2 替换所有3 值!我刚刚解决了这个问题。对困惑感到抱歉。我更新了我的帖子。

标签: python pandas dataframe conditional-statements


【解决方案1】:

由于组以2/3 开始/结束,条件df['Value'].ge(10) 已经在中间搜索那些行。你只需要在这种情况下做groupby().transform('any')

mask = df['Value'].ge(10).groupby(df['Category']).transform('any')

df[mask]

输出:

          Date  Category  Value
3   2015-06-05         2      3
4   2015-06-06         2      8
5   2015-06-07         2     11
6   2015-06-08         2      3
7   2015-06-09         4      3
8   2015-06-10         4      5
9   2015-06-11         4     12
10  2015-06-12         4      3
14  2015-06-16         8      3
15  2015-06-17         8      6
16  2015-06-18         8     10
17  2015-06-19         8      3

【讨论】:

  • 对不起!我才意识到我在帖子中犯了一个错误。我的意思是用2 替换所有3 值!所以这只是2s 之间的值的问题,不需要在3s 之间。我刚刚更新了我的帖子。对困惑感到抱歉!仍然会应用您的代码建议吗?
  • @LostinSpatialAnalysis 是的,23 都小于 10,因此不会影响条件 >=10
【解决方案2】:

pandas 中的groupby 可用作返回子集数据帧的迭代器,以便可以对每个子数据帧进行操作。举个例子:

cats = reduce(lambda x, y: x+y, [[i]*4 for i in range(4)])
vals = [random.randint(0, 20) for _ in range(len(cats))]
df = pd.DataFrame({"category": cats, "values": vals})

这个随机数据框可能如下所示:

然后您可以迭代并将逻辑专门应用于每个子类别,如下所示:

res = []
for _, sub_df in df.groupby("category"):
    if sub_df["values"].max() >= 10:
        res.append(sub_df)
if res:
    df = pd.concat(res)

此代码查看每个子集,如果满足条件,则将其附加到列表中。然后将此数据帧列表(如果不为空)连接到一个数据帧中。注意:这里的顺序现在将按分组变量排序。如果出现此错误,您只需使用 df.sort_index() 按原始索引重新排序即可。

【讨论】:

    猜你喜欢
    • 2020-03-09
    • 2019-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-28
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多