Определите среднее значение «данных», где максимальное число CONTINUOUS cond = True

У меня есть панда Dataframe с столбцом «data» и «cond» (- ition). Мне нужно среднее значение (столбца данных) строк с наибольшим количеством объектов CONTINUOUS True в 'cond'.

Example DataFrame: cond data 0 True 0.20 1 False 0.30 2 True 0.90 3 True 1.20 4 True 2.30 5 False 0.75 6 True 0.80 Result = 1.466, which is the mean value of row-indexes 2:4 with 3 True 

Я не смог найти «векторизованное» решение с помощью метода groupby или pivot. Поэтому я написал func, который петли строки. К сожалению, это занимает около часа на 1 миллион линий, что является долгой. К сожалению, украшение @jit не уменьшает длительность измеряемой величины.

Данные, которые я хочу проанализировать, – это проект мониторинга в течение одного года, и у меня есть каждые 3 часа DataFrame с одним миллионом строк. Таким образом, около 3000 таких файлов.

Эффективное решение будет очень важным. Я также очень благодарен за решение в numpy.

2 Solutions collect form web for “Определите среднее значение «данных», где максимальное число CONTINUOUS cond = True”

Вот основанный на NumPy подход –

 # Extract the relevant cond column as a 1D NumPy array and pad with False at # either ends, as later on we would try to find the start (rising edge) # and stop (falling edge) for each interval of True values arr = np.concatenate(([False],df.cond.values,[False])) # Determine the rising and falling edges as start and stop start = np.nonzero(arr[1:] > arr[:-1])[0] stop = np.nonzero(arr[1:] < arr[:-1])[0] # Get the interval lengths and determine the largest interval ID maxID = (stop - start).argmax() # With maxID get max interval range and thus get mean on the second col out = df.data.iloc[start[maxID]:stop[maxID]].mean() 

Тест времени выполнения

Подходы как функции –

 def pandas_based(df): # @ayhan's soln res = df['data'].groupby((df['cond'] != df['cond'].shift()).\ cumsum()).agg(['count', 'mean']) return res[res['count'] == res['count'].max()] def numpy_based(df): arr = np.concatenate(([False],df.cond.values,[False])) start = np.nonzero(arr[1:] > arr[:-1])[0] stop = np.nonzero(arr[1:] < arr[:-1])[0] maxID = (stop - start).argmax() return df.data.iloc[start[maxID]:stop[maxID]].mean() 

Сроки –

 In [208]: # Setup dataframe ...: N = 1000 # Datasize ...: df = pd.DataFrame(np.random.rand(N),columns=['data']) ...: df['cond'] = np.random.rand(N)>0.3 # To have 70% True values ...: In [209]: %timeit pandas_based(df) 100 loops, best of 3: 2.61 ms per loop In [210]: %timeit numpy_based(df) 1000 loops, best of 3: 215 µs per loop In [211]: # Setup dataframe ...: N = 10000 # Datasize ...: df = pd.DataFrame(np.random.rand(N),columns=['data']) ...: df['cond'] = np.random.rand(N)>0.3 # To have 70% True values ...: In [212]: %timeit pandas_based(df) 100 loops, best of 3: 4.12 ms per loop In [213]: %timeit numpy_based(df) 1000 loops, best of 3: 331 µs per loop 

Используя подход из расчета числа конкретных последовательных равных значений в векторном виде в пандах :

 df['data'].groupby((df['cond'] != df['cond'].shift()).cumsum()).agg(['count', 'mean'])[lambda x: x['count']==x['count'].max()] Out: count mean cond 3 3 1.466667 

Для индексирования по вызываемому требуется 0.18.0, для более ранних версий вы можете:

 res = df['data'].groupby((df['cond'] != df['cond'].shift()).cumsum()).agg(['count', 'mean']) res[res['count'] == res['count'].max()] Out: count mean cond 3 3 1.466667 

Как это работает:

Первая часть, df['cond'] != df['cond'].shift() возвращает булевский массив:

 df['cond'] != df['cond'].shift() Out: 0 True 1 True 2 True 3 False 4 False 5 True 6 True Name: cond, dtype: bool 

Поэтому значение равно False, если строка такая же, как и выше. Это означает, что если вы возьмете кумулятивную сумму, эти строки (последовательные) будут иметь одинаковое число:

 (df['cond'] != df['cond'].shift()).cumsum() Out: 0 1 1 2 2 3 3 3 4 3 5 4 6 5 Name: cond, dtype: int32 

Поскольку groupby принимает любую группу для группировки (нет необходимости передавать столбец, вы можете передать произвольный список), это можно использовать для группировки результатов. .agg(['count', 'mean'] часть просто дает соответствующие подсчеты и средства для каждой группы, и в конце она выбирает ту, которая имеет наибольший счет.

Обратите внимание, что это также сгруппировало бы последовательные False. Если вы хотите рассматривать только последовательные True, вы можете изменить группу группировки на:

 ((df['cond'] != df['cond'].shift()) | (df['cond'] != True)).cumsum() 

Поскольку мы хотим, чтобы False, когда условие True, условие стало «не равно строке ниже ИЛИ не True». Таким образом, исходная строка изменится на:

 df['data'].groupby(((df['cond'] != df['cond'].shift()) | (df['cond'] != True)).cumsum()).agg(['count', 'mean'])[lambda x: x['count']==x['count'].max()] 
  • Почему реализация JITted Python все еще медленная?
  • Как сделать этот блок кода python коротким и эффективным
  • Ajax v., Включая данные в HTML
  • Как заменить первые n элементов в каждой строке кадра данных, которые превышают определенный порог
  • Неожиданная версия «Экспоненциально взвешенная скользящая средняя», эквивалентная pandas.ewm (). Mean ()
  • Почему так быстро?
  • Осциллирующая скорость обработки в скрипте python с использованием pysam.TabixFile для комментирования показаний
  • Код Cython в 3-4 раза медленнее кода Python / Numpy?
  • Достоинства Bash Script v. Python Script для Shell-Command-Heavy Utility
  • Python - ускорить преобразование категориальной переменной в ее числовой индекс
  • Каков самый быстрый способ подготовки данных для RNN с numpy?
  •  
    Interesting Posts for Van-Lav

    Как скрыть консоль, когда я использую os.system () или subprocess.call ()?

    Python, используя ctypes для создания оболочки класса C ++

    Разбить массив NumPy в соответствии со значениями в массиве (условие)

    Как запустить действие для всех запросов в Flask?

    Экспорт кадра данных Pandas с текстовым столбцом, содержащим текст utf-8 и URL-адреса в Excel

    Избегайте вставки дубликатов в список Python с пониманием

    Закрытие в Python

    Установка PIL с пипсом

    Не удается запустить работника сельдерей на Windows 10 с помощью программы «PicklingError»

    Выделенный список длинной сортировки с WTForms

    Сделайте столько копий, сколько существует количество версий для файла в plone?

    imaplib – Какое правильное имя папки для Archive / All Mail в Gmail?

    Selenium Python: наведите курсор мыши на круговую диаграмму с небольшими участками, зависающими на неправильных разделах

    Утечки памяти Django 1.6 и Celery 3.0

    Статическая структура Django

    Python - лучший язык программирования в мире.