#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. Итак, вам нужна любая запись, которая является частью группы из трех последовательных выбросов? На будущее полезно иметь как можно больше подробностей о том, что вы хотите в вопросе. Получение этих групп возможно, но я не думаю, что это тривиально — я добавлю один вариант к своему ответу.