【问题标题】:How to check for stuck data in a pandas data frame如何检查熊猫数据框中的卡住数据
【发布时间】:2020-11-24 00:37:34
【问题描述】:

为了清楚起见,已根据 cmets 对这个问题进行了编辑

目标:基于组标记数据框列中可变数量的卡住/重复值。

所需的解决方案:所需的解决方案应满足以下条件:

  1. 速度和简洁很重要
  2. 解决方案应接受可变数量的阈值作为输入,用于标记每个区域的卡住/重复值。 例如: {"Zone1": 4 , "Zone2":2} ->表示在Zone1中,需要有4个连续的重复值才能被逻辑标记,而在Zone2中,至少有2个或更多的重复值应该触发标记
  3. 请尽可能添加 cmets 以便于理解
  4. 最好使用 Pandas 和/或 Numpy
  5. 在一个包含 87600 个值的测试数据帧上为您的解决方案计时(生成一个包含 87600 个值的数据帧)

输入数据/问题表述:

import pandas as pd
import numpy as np
from random import randint

# Generate some random data
ts_index = pd.date_range("1/1/2019", periods=24, freq="1H")
v1 = [randint(1, 100) for i in range(24)]
v2 = [2] * 24
v3 = [2, 2, 2, 2, 4, 4, 0, 2, 2, 1, 9, 2, 4, 1, 2, 2, 0, 2, 1, 8, 1, 7, 3, 5]
test_df = pd.DataFrame({"v1": v1, "v2": v2, "v3": v3}, index=ts_index)
print(test_df) 

现在,示例输出应如下所示。

【问题讨论】:

  • 您好,可能会有所帮助,但同时存在 2 个问题对未来的读者来说并不是很好。也可以修改标题以对未来的读者更有帮助。还请提供一个非常紧凑的输入和相应的输出数据框(没有不必要的代码或列),例如像您的随机数据框,但已经包括那些“区域”并且具有描述性的列名并且没有不必要的列。
  • 我看到您的输出有些不一致,为什么6:00v3 中是FALSE4:00TRUE?当前行是否包含在重复中?请解释一下。
  • 假设您在第 4 小时引用第 v3 列中的数据,那么您是正确的,它们在第 4 小时和第 5 小时应该是 FALSE,因为我们正在寻找 4 个重复值来触发标志。

标签: python python-3.x pandas dataframe pandas-groupby


【解决方案1】:

首先我们得到列的绝对差,然后是cumsum()

假设如果一个值没有变化,则差异的累积和将保持不变,我们可以使用 pandas .shift()

我们必须将 zone1 中的每个值与上面的 4 行进行比较。 zone2 类似。

import pandas as pd
import numpy as np
import datetime


# Generate some random data
ts_index = pd.date_range("1/1/2019", periods=24, freq="1H")
v1 = [random.randint(1, 100) for i in range(24)]
v2 = [2] * 24
v3 = [2, 2, 2, 2, 4, 4, 0, 2, 2, 1, 9, 2, 4, 1, 2, 2, 0, 2, 1, 8, 1, 7, 3, 5]
df = pd.DataFrame({"v1": v1, "v2": v2, "v3": v3}, index=ts_index)
df1 = df.diff().fillna(0)

# Add hour and time of day to create flag
df['Hour'] = df.index.hour
df['Flag'] = np.where((df['Hour'] <= 8) | (df['Hour'] >= 18), 'Zone1', 'Zone2')
df1['Flag'] = np.where((df['Hour'] <= 8) | (df['Hour'] >= 18), 'Zone1', 'Zone2')

df1[["v1", "v2","v3"]] = np.abs(df1[["v1", "v2","v3"]])
df1[["v1", "v2","v3"]] = df1.groupby("Flag")["v1", "v2","v3"].cumsum()
columns = ["v1","v2","v3"]

z1_p = 3
z2_p = 1

for col in columns:
    df["Flag_"+col] = (np.array(df1[col].shift(z1_p) == df1[col]) & np.array(df1["Flag"] == "Zone1")) | \
(np.array(df1[col].shift(z2_p) == df1[col]) & np.array(df1["Flag"] == "Zone2"))
    for element in df[df["Flag_"+col] == True].index:
        if df.loc[element]["Flag"] == "Zone1":
            for i in range(1,4):
                a = a.append(pd.Index([element - datetime.timedelta(hours=i)]))
        else:
            a = a.append(pd.Index([element - datetime.timedelta(hours=1)]))
    df.at[a,"Flag_"+col] = True

df

输出:

                    v1  v2  v3  Hour    Flag    Flag_v1 Flag_v2 Flag_v3
2019-01-01 00:00:00 31  2   2   0       Zone1   False   True    True
2019-01-01 01:00:00 93  2   2   1       Zone1   False   True    True
2019-01-01 02:00:00 48  2   2   2       Zone1   False   True    True
2019-01-01 03:00:00 56  2   2   3       Zone1   False   True    True
2019-01-01 04:00:00 9   2   4   4       Zone1   False   True    False
2019-01-01 05:00:00 75  2   4   5       Zone1   False   True    False
2019-01-01 06:00:00 29  2   0   6       Zone1   False   True    False
2019-01-01 07:00:00 61  2   2   7       Zone1   False   True    False
2019-01-01 08:00:00 64  2   2   8       Zone1   False   True    False
2019-01-01 09:00:00 82  2   1   9       Zone2   False   True    False
2019-01-01 10:00:00 13  2   9   10      Zone2   False   True    False
2019-01-01 11:00:00 97  2   2   11      Zone2   False   True    False
2019-01-01 12:00:00 74  2   4   12      Zone2   False   True    False
2019-01-01 13:00:00 26  2   1   13      Zone2   False   True    False
2019-01-01 14:00:00 77  2   2   14      Zone2   False   True    True
2019-01-01 15:00:00 39  2   2   15      Zone2   False   True    True
2019-01-01 16:00:00 79  2   0   16      Zone2   False   True    False
2019-01-01 17:00:00 35  2   2   17      Zone2   False   True    False
2019-01-01 18:00:00 65  2   1   18      Zone1   False   True    False
2019-01-01 19:00:00 74  2   8   19      Zone1   False   True    False
2019-01-01 20:00:00 72  2   1   20      Zone1   False   True    False
2019-01-01 21:00:00 23  2   7   21      Zone1   False   True    False
2019-01-01 22:00:00 28  2   3   22      Zone1   False   True    False
2019-01-01 23:00:00 59  2   5   23      Zone1   False   True    False

【讨论】:

  • 感谢您的尝试,但结果与我要求的非常不同。我将更新我的原始帖子以相应地反映预期的输出
  • 提供一个示例输出,然后我们会看到
  • 请发布完整的解决方案并附上适当的参考资料。以目前的形式,我无法让它工作,我认为有一些拼写错误,您指的是可能存在或不存在的列标志。我不知道df1是什么?请清理它,以便我可以实际测试它。另外,我希望包含当前行 - 只需回答您之前的问题
  • 你有它。
  • 我按照您的指导删除了 .shift(1) 并将 z1_p 和 z2_p 分别减少了 1。虽然结果很接近,但仍然存在一些问题。我在屏幕截图上标记它们。 i.stack.imgur.com/G6dhJ.png
【解决方案2】:

这行得通吗

import pandas as pd, numpy as np
from random import randint


def processGroup(zone, ZoneGroup):
    ZoneGroup.sort_index(inplace=True)
    repeatation = repeatations[zone]
    
    repeat_counts = [0]*len(cols)
    previous_value = [None]*len(cols)
    
    for i, record in ZoneGroup.iterrows():
        for j, c in enumerate(cols):
            if previous_value[j] == record[c]:
                repeat_counts[j] += 1
            else:
                repeat_counts[j] = 0
                
            if repeat_counts[j] >= repeatation:
                test_df.at[i, c+'RepeatFlag']=True
                
            previous_value[j] = record[c]

TotalRecords = 87600 #24*10
ts_index = pd.date_range("1/1/2019", periods=TotalRecords, freq="1H")
v1 = [randint(1, 2) for i in range(TotalRecords)]
v2 = [randint(1, 3) for i in range(TotalRecords)]
v3 = [randint(1, 5) for i in range(TotalRecords)]

test_df = pd.DataFrame({"v1": v1, "v2": v2, "v3": v3}, index=ts_index)
test_df['Zone'] = pd.Series(test_df.index).apply(lambda t: 'Zone'+ str(int((t.hour+t.minute/60+t.second/3600)// 8 + 1))).to_list()

# You can tweak repaet values here
repeatations = {'Zone1':4, 'Zone2':3, 'Zone3':2}
cols = test_df.columns[:-1]

#test_df[cols+'RepeatFlag']=False
for c in cols+'RepeatFlag':
    test_df[c]=False

for i, g in test_df.groupby('Zone'):
    processGroup(i, g)
    
print(test_df)
repeat_df = test_df[test_df.v1RepeatFlag | test_df.v2RepeatFlag | test_df.v3RepeatFlag]
print(repeat_df)

【讨论】:

  • Kuldip,您的代码引发了 Key Error 。 KeyError:“[Index(['v1RepeatFlag', 'v2RepeatFlag', 'v3RepeatFlag'], dtype='object')] 中没有 [列]”
  • 我在 Jupyter Notebook 中测试过,可能 test_df[cols+'RepeatFlag']=False 因为 pandas 版本的不同而不起作用。请尝试编辑后的代码。
【解决方案3】:

我已经测试了代码。查看笔记本的屏幕截图。尝试一次编辑的代码。

【讨论】:

    猜你喜欢
    • 2017-12-29
    • 1970-01-01
    • 2022-07-21
    • 2022-08-09
    • 2018-08-03
    • 1970-01-01
    • 2018-05-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多