Pandas/Python 根据旧列和前一行的条件创建新列和行

问题描述 投票:0回答:1

我正在尝试分析数据框中的一些数据,并确定数据中何时出现空闲时间(显示为平点)。 这些平点是当 disp 值从 > 520 到 ~ 225 时出现的。我想创建一个新列来充当这些时间的标签。

这是我的一些数据的一小段浓缩摘录。 完整数据集大约有 270,000 行,并且可能很嘈杂。 空闲期的开始是第 150 行,空闲期的结束是第 157 行。

           disp      temp  
148  528.253551  0.908375
149  537.832220  0.944138
150  225.073475  0.890493
151  225.247861  0.892878
152  225.487333  0.895262
153  225.515279  0.926256
154  225.515003  0.909567
155  225.518680  0.901222
156  225.537893  0.927448
157  225.068878  0.865460
158  540.460613  0.873804
159  531.048884  0.865460

我想生成的输出是

           disp      temp      state
148  528.253551  0.908375       None
149  537.832220  0.944138       None
150  225.073475  0.890493   idl_strt
151  225.247861  0.892878       idle
152  225.487333  0.895262       idle
153  225.515279  0.926256       idle
154  225.515003  0.909567       idle
155  225.518680  0.901222       idle
156  225.537893  0.927448       idle
157  225.068878  0.865460   idl_ends
158  540.460613  0.873804       None
159  531.048884  0.865460       None

有矢量化的方法来做到这一点吗? 通过 pd.apply 方法调用的函数可以查看之前的行而不首先创建额外的移位列吗?

我已经能够使用以下代码使用“idl_start”和“idl_ends”填充状态列的正确行

def _idlefinder(self, row):
    """Logic for finding idles start and end"""
    if (row["disp"] + 250.0) < row["nextdisp"]:  # find large drops in disp value
        return "idle_strt"
    elif row["disp"] + 250 < row["lastdisp"]:    # find large increases in disp value
        return "idle_end"

df["lastdisp"] = df["disp"].shift(1)
df["nextdisp"] = df["disp"].shift(-1)
df["status"] = df.apply(_idlefinder, axis=1)  # label idle_start and idle_end
df.drop(columns=["nextdisp", "lastdisp"], inplace=True)

但这既不优雅也不完整的解决方案。 我要问的关键部分是如何填充“idl_strt”和“idl_ends”之间的行,因为数据的其余部分(带有噪音读数的上升和暂停)也必须被识别和标记。 我的偏好是不要逐行浏览数据,因为我使用的是数据框。

该程序的早期版本确实在列表中逐行解析这些数据,但变得有点冗长并且需要调整或修改。

python pandas dataframe function apply
1个回答
0
投票

您有多种方法可以矢量地实现这一目标。下面是一个示例,它根据接近 225 的值(容差为 ±2)识别平坦区域,并在上一个/下一个值 >520 时突出显示开始/结束。它使用

shift
numpy.select
:

def idle_finder(col, flat_value=225, flat_tol=2, high_thresh=520):
    m1 = col.gt(high_thresh)
    m2 = col.sub(flat_value).abs().lt(flat_tol)
    return pd.Series(np.select([m1.shift()&m2, m1.shift(-1)&m2, m2],
                               ['idl_strt', 'idl_ends', 'idle'],
                               ''),
                     index=col.index
                    ).replace('', None)
            
df['status'] = idle_finder(df['disp'])

输出:

           disp      temp    status
148  528.253551  0.908375      None
149  537.832220  0.944138      None
150  225.073475  0.890493  idl_strt
151  225.247861  0.892878      idle
152  225.487333  0.895262      idle
153  225.515279  0.926256      idle
154  225.515003  0.909567      idle
155  225.518680  0.901222      idle
156  225.537893  0.927448      idle
157  225.068878  0.865460  idl_ends
158  540.460613  0.873804      None
159  531.048884  0.865460      None

如果要确保空闲期在大于 520 的值之后/之前开始和结束,可以使用附加掩码:

def idle_finder(col, flat_value=225, flat_tol=2, high_thresh=520):
    m1 = col.gt(high_thresh)
    m2 = col.sub(flat_value).abs().lt(flat_tol)
    m3 = m1.mask(m2)
    m4 = m3.ffill() & m3.bfill() & m2
    return pd.Series(np.select([m1.shift()&m4, m1.shift(-1)&m4, m4],
                               ['idl_strt', 'idl_ends', 'idle'],
                               ''),
                     index=col.index
                    ).replace('', None)
            
df['status'] = idle_finder(df['disp'])

输出:

           disp      temp    status
148  528.253551  0.908375      None
149  337.832220  0.944138      None
150  225.073475  0.890493      None
151  225.247861  0.892878      None
152  225.487333  0.895262      None
153  225.515279  0.926256      None
154  525.515003  0.909567      None
155  225.518680  0.901222  idl_strt
156  225.537893  0.927448      idle
157  225.068878  0.865460  idl_ends
158  540.460613  0.873804      None
159  531.048884  0.865460      None

中间体:

           disp      temp    status     m1     m2  m1.shift()&m2  m1.shift(-1)&m2     m3     m4  m1.shift()&m4  m1.shift(-1)&m4
148  528.253551  0.908375      None   True  False          False            False   True  False          False            False
149  337.832220  0.944138      None  False  False          False            False  False  False          False            False
150  225.073475  0.890493      None  False   True          False            False    NaN  False          False            False
151  225.247861  0.892878      None  False   True          False            False    NaN  False          False            False
152  225.487333  0.895262      None  False   True          False            False    NaN  False          False            False
153  225.515279  0.926256      None  False   True          False             True    NaN  False          False            False
154  525.515003  0.909567      None   True  False          False            False   True  False          False            False
155  225.518680  0.901222  idl_strt  False   True           True            False    NaN   True           True            False
156  225.537893  0.927448      idle  False   True          False            False    NaN   True          False            False
157  225.068878  0.865460  idl_ends  False   True          False             True    NaN   True          False             True
158  540.460613  0.873804      None   True  False          False            False   True  False          False            False
159  531.048884  0.865460      None   True  False          False            False   True  False          False            False
© www.soinside.com 2019 - 2024. All rights reserved.