Этот вопрос связан с предыдущим вопросом, связанным здесь. Количество последовательных значений выше определенного отсечения и немного с ответом, предоставленным @kvantour
Так что в моем случае у меня есть файл вроде этого (Sample Input)
0.34
0.3432
0.32
0.35
0.323
0.3623
0.345
0.32
0.31
0.378
0.34
0.35
0.342
Во-первых: в моем случае, если два или более последовательных значения удовлетворяют заданному обрезанию c = 0,33, я называл его B. Это задается условием m, см. Здесь: Число последовательных значений выше определенного обрезания
Во-вторых: если значение c равно 0,33, и я хочу, чтобы значения были ниже, чем c, он будет печатать 0,32 и 0,323, но я также хочу распечатать 0,35, потому что это всего лишь одно появление выше c, которое не соответствует моему правилу, как указано в m следовательно, он также будет распечатан. На это ответил @kvantour. Я назвал это F
Таким образом, в моих $ 2 состояния выглядят так: BCBCB
Поэтому я могу подсчитать количество разбитых (B) событий, таких как следующие (Sample Output)
2 #this corresponds to no. of frames in first B
2 #this corresponds to no. of frames in second B
4 #this corresponds to no. of frames in third B
Есть ли способ подсчитать и распечатать нет. разбитых событий как список?
Определите количество кадров в строке. Если только один кадр сломан (но предыдущий и следующий кадр хороши), это нормально, проигнорируйте это. Рамка сломана, если ее значение выше отсечки (0,33).
from itertools import groupby
Чтение на входе
def get_input():
with open('input.txt') as f:
next(f) # skip the first line
input_list = []
Я разбиваю каждую строку на основе пробела и игнорируя номер кадра
for line in f:
input_list.append(float(line.split()[1]))
return input_list
Это вспомогательная функция, которая возвращает true или False, если значение находится выше отсечки
def above_cutoff(x, cutoff):
return x > cutoff
Здесь интересная часть. Мы группируем значения на основе того, находятся ли они выше или ниже критериев. Мы возвращаемся к группе и можем проверить, сколько в ней.
В цикле for
ниже указанная above
переменная будет True
если группа выше обрезания. g
- генератор, содержащий группу. Я просто конвертирую его в список, потому что это проще в использовании и проверяет длину.
def count_broken(input_list, cutoff):
# returns list with number of values in a row above threshold
state = []
for above, g in groupby(input_list, lambda x: above_cutoff(x, cutoff)):
group = list(g)
print(above, group, len(group))
Если группа длиннее 1, она соответствует вашим критериям, поэтому добавьте ее длину
if above and len(group) > 1:
state.append(len(group))
return state
input_list = get_input()
print(*count_broken(input_list, 0.33), sep='\n')
Операторы печати в цикле выводят это:
True [0.34, 0.3432] 2
False [0.32] 1
True [0.35] 1 # while this group is True/in state B/broken, ignore it cause it is just 1 frame.
False [0.323] 1
True [0.3623, 0.345] 2
False [0.32, 0.31] 2
True [0.378, 0.34, 0.35, 0.342] 4
Конечный результат:
2
2
4
Я основывал свое решение на принятом ответе на этот вопрос: Возьмите список, верните список True/False, основанный на последовательных повторяющихся значениях
awk
на помощь (с друзьями)
$ awk 'NR>1{print ($2>0.33)}' file | uniq -c | awk '$2 && $1>1{print $1}'
2
2
4
объяснение
NR>1{print ($2>0.33)}
напечатайте 1 или 0, выполняется ли условие$2>0.33
, пропуская первую строку заголовка.
uniq -c
подсчитывает последовательные повторяющиеся значения (длина цепи)
$2 && $1>1{print $1}
печатать длину цепочки, когда значение отличное от нуля (здесь оно 1), а длина больше единицы, как указано OP.
groupby
группирует вещи относительно того, находятся ли они выше вашего порога или нет. Если они есть,above
этоTrue
. При проверке длиныgroup
и проверках логического значенияabove
, вы можете проверить , если этаgroup
является одним вы хотите сделать что - то с.