Как проверить наличие последовательной метки времени в списке

#python #python-3.x #list #python-2.7

#python #python-3.x #Список #python-2.7

Вопрос:

У меня есть словарь, который имеет следующие значения:

 {
'original_data': [{'1600995180': 64.71666666666667, '1600995240': 0.17222222222222222, '1600995300': 0.16111111111111112, '1600995360': 0.6666666666666666, '1600995420': 0.17222222222222222, '1600995480': 0.0, '1600995540': 0.0, '1600995600': 0.0, '1600995660': 0.0, '1600995720': 0.0, '1600995780': 0.0, '1600995840': 1.0, '1600995900': 1.0, '1600995960': 1.0, '1600996020': 0.0, '1600996080': 0.0, '1600996140': 1.0, '1600996200': 1.0, '1600996260': 1.0, '1600996320': 0.0, '1600996380': 0.0, '1600996440': 0.0, '1600996500': 0.0, '1600996560': 0.0, '1600996620': 0.0, '1600996680': 0.0, '1600996740': 0.0, '1600996800': 0.0, '1600996860': 0.0, '1600996920': 10.86944444444444, '1600996980': 106.88333333333331}],
'outliers': [0.16111111111111112, 0.17222222222222222, 0.17222222222222222, 0.6666666666666666, 10.86944444444444, 64.71666666666667, 106.88333333333331]
}
  

original_data Содержит список значений как {timestamp: value} . Выбросы содержат только выбросы value из original_data.

Я хочу на самом деле сравнить каждое value из outlier них, а затем посмотреть original_data , происходят ли эти значения последовательно с меткой времени. Временная метка разнесена на 1 минуту для каждой точки данных

Комментарии:

1. почему original_data список содержит только 1 элемент (dict)

Ответ №1:

 def consecutively(data):
    values = data['original_data'][0].values()
    out = data['outliers']
    b = False
    for v in values:
        if v in out:
            if b:
                return True
            else:
                b = True
        else:
            b = False
    return False
  

Это сработало бы!

PS Я не уверен в использовании ‘original_data’ в качестве списка, содержащего только 1 элемент, который является словарем. Почему не использовать dict напрямую?

Комментарии:

1. я также хочу убедиться, что временные метки учтены, так как я хочу проверить последовательные

Ответ №2:

У меня есть предложение, которое заключается в том, чтобы справиться с этим в pandas DataFrame .

Я вызову ваш оригинальный словарь data . Это немного странный формат, но с ним можно легко справиться:

 import pandas as pd  # pip install pandas if you don't have it

df = pd.DataFrame(data["original_data"]).T.reset_index()

df.columns = ["timestamp", "value"]  # change the column names to something descriptive

### OPTIONAL (convert UNIX timestamps to pandas Timestamp to makes things clearer)
df["timestamp"] = pd.to_datetime(df.timestamp, unit="s")
###

df["outlier"] = df.value.isin(data["outliers"])  # add a column to show whether a value was an outlier

  

На этом этапе вы можете закончить! Вы можете проверить df и увидеть:

              timestamp       value  outlier
0  2020-09-25 00:53:00   64.716667     True
1  2020-09-25 00:54:00    0.172222     True
2  2020-09-25 00:55:00    0.161111     True
3  2020-09-25 00:56:00    0.666667     True
4  2020-09-25 00:57:00    0.172222     True
5  2020-09-25 00:58:00    0.000000    False
6  2020-09-25 00:59:00    0.000000    False
7  2020-09-25 01:00:00    0.000000    False
8  2020-09-25 01:01:00    0.000000    False
9  2020-09-25 01:02:00    0.000000    False
10 2020-09-25 01:03:00    0.000000    False
11 2020-09-25 01:04:00    1.000000    False
12 2020-09-25 01:05:00    1.000000    False
13 2020-09-25 01:06:00    1.000000    False
14 2020-09-25 01:07:00    0.000000    False
15 2020-09-25 01:08:00    0.000000    False
16 2020-09-25 01:09:00    1.000000    False
17 2020-09-25 01:10:00    1.000000    False
18 2020-09-25 01:11:00    1.000000    False
19 2020-09-25 01:12:00    0.000000    False
20 2020-09-25 01:13:00    0.000000    False
21 2020-09-25 01:14:00    0.000000    False
22 2020-09-25 01:15:00    0.000000    False
23 2020-09-25 01:16:00    0.000000    False
24 2020-09-25 01:17:00    0.000000    False
25 2020-09-25 01:18:00    0.000000    False
26 2020-09-25 01:19:00    0.000000    False
27 2020-09-25 01:20:00    0.000000    False
28 2020-09-25 01:21:00    0.000000    False
29 2020-09-25 01:22:00   10.869444     True
30 2020-09-25 01:23:00  106.883333     True
  

и это говорит вам о том, что вы хотите знать. В качестве альтернативы, если вы хотите явно указать, предшествовало ли внешнему значению другое внешнее значение, вы могли бы сделать

 df["is_outlier_preceded_by_outlier"] = df.outlier amp; df.outlier.diff().eq(False)
  

и это создает столбец, значение которого True равно значению, которое было выбросом и которому предшествовал другой выброс, и False в противном случае.

df.query("is_outlier_preceded_by_outlier") затем вернет только те случаи, когда это так True .

РЕДАКТИРОВАТЬ: альтернативно (менее очевидно, но более расширяемо)

 df["is_outlier_preceded_by_outlier"] = df.outlier.rolling(2).sum().eq(2)
  

тоже будет работать, и вы можете изменить 2 (в обоих местах) на любое число, которое вам нравится, чтобы искать прогоны из N последовательных выбросов.

РЕДАКТИРОВАТЬ 2: итак, если вам нужны значения для каждой группы из N последовательных выбросов, это немного сложнее:

 groups = df.outlier.diff().ne(0).cumsum()

is_part_of_long_group = df.outlier.groupby(groups).transform("size").ge(3)

df["one_of_many_outliers"] = is_part_of_long_group amp; df.outlier

df.query("one_of_many_outliers").value
  

Сначала нам нужно будет определить группы идентичных значений в outlier столбце. df.outlier.diff().ne(0).cumsum() создает ряд, который мы будем использовать в качестве группирующего индекса, с постепенно увеличивающимися значениями каждый раз, когда следующее значение в outlier столбце отличается от предыдущего.

Затем мы группируем outlier столбец по этому «индексу» и используем transform метод для получения размера каждой группы последовательных значений. Наконец, мы проверяем, является ли размер этой группы больше или равен 3, т. Е. Мы ищем группы последовательных значений длиной не менее 3 элементов.

Обратите внимание, что в то agg("size") время как даст нам каждую группу и ее размер, transform("size") получает размер каждой группы и отображает ее обратно в исходную df.outlier серию.

Наконец, нас не интересуют последовательные не-выбросы, поэтому мы проверяем, являются ли значения как выбросами, так и частью длинной группы последовательных равных значений.

Комментарии:

1. Допустим, я хочу проверить, являются ли 3 выбросов последовательными, что я могу для этого сделать

2. Для этого я бы рекомендовал df.outlier.rolling(3).sum().eq(3) . Эта серия будет True для любого случая, когда что-то является третьим последовательным выбросом подряд (это будет работать для любого числа, просто измените оба 3-х — на самом деле я хотел бы, чтобы я подумал об этом в первую очередь и поместил его в ответ).

3. Ах нет, не это,. итак, что я хочу сделать, это в основном посмотреть, являются ли, скажем, 3 True последовательными, тогда я хочу сосчитать все 3 и поместить их в список вне df.

4. Причина в том, что у меня есть не только один dict, но и 10 dict, и я хочу посмотреть, являются ли 3 значения выбросов последовательными в каждом исходном значении, тогда я просто обновлю это количество в списке

5. Итак, вам нужна любая запись, которая является частью группы из трех последовательных выбросов? На будущее полезно иметь как можно больше подробностей о том, что вы хотите в вопросе. Получение этих групп возможно, но я не думаю, что это тривиально — я добавлю один вариант к своему ответу.