Время выполнения оптимизации разделения фрейма данных на вложенные фреймы данных в Python

#python #pandas #dataframe #optimization

#python #pandas #фрейм данных #оптимизация

Вопрос:

У меня есть pandas DF (df_main), который я пытаюсь разделить на разные подмножества. Набор данных выглядит примерно так:

 a b c d e f

1 1 1 2 1 2   1.

2 3 2 1 2 1   2.

3 1 3 1 3 1   3.

3 2 1 3 4 1   4.

3 1 3 4 2 1   5.

2 1 2 3 4 2   6.

1 2 3 4 5 3   7.
  

Я хочу разделить полный файл df на основе элемента столбца a и следующего за ним элемента на 3 подмножества.

Подмножество 1: увеличение значений col(a) , поэтому 1., 2., 3.

Подмножество 2: значение col(a) остается постоянным, поэтому 3., 4., 5.

Подмножество 3: уменьшающееся значение col (a) , поэтому 5., 6., 7.

Мой код выглядит на данный момент следующим образом:

 df1_new = pd.DataFrame(columns=['a', 'b', 'c', 'd', 'e', 'f'])
df2_new = pd.DataFrame(columns=['a', 'b', 'c', 'd', 'e', 'f'])
df3_new = pd.DataFrame(columns=['a', 'b', 'c', 'd', 'e', 'f'])

for j in range(len(df_main['a'])):
    if df_main['a'][j] == df_main['a'][j   1]:
        df1_new = df1_new.append(df_main.iloc[j])
    if df_main['a'][j] > df_main['a'][j   1]:
        df2_new = df2_new.append(df_main.iloc[j])
    if df_main['a'][j] < df_main['a'][j   1]:
        df3_new = df3_new.append(df_main.iloc[j])
  

Из-за того, что df_main имеет длину 1 353 419 строк, ему требуется (atm) около 15 часов для завершения выполнения.

Есть ли какие-либо варианты оптимизации времени, необходимого для прохождения через df и разделения его?

Я немного рассказал о векторизации numpy, но я не уверен, будет ли это правильным решением здесь.

Шаблон, основанный на увеличении, уменьшении и постоянных значениях, можно увидеть здесь

введите описание изображения здесь

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

1. Всегда ли ваш df содержит сначала возрастающие значения, затем те же значения, а затем уменьшающиеся значения?

2. Привет, Шубхам, нет, это не всегда следует одному и тому же шаблону. Я добавлю визуализацию шаблона.

3. Итак, вы хотите, чтобы все возрастающие значения были в одном наборе, все уменьшающиеся значения в другом наборе …, верно?

4. Правильно, и если значение [i] == value[i 1], я хочу, чтобы данные сохранялись в третьем подмножестве. Моя главная проблема — время выполнения, оно слишком длинное.

Ответ №1:

Используйте Series.gt , Series.lt и Series.eq наряду с Series.shift для создания логических масок m1 , m2 и m3 , затем используйте эти маски для фильтрации / разделения фрейма данных по соответствующим категориям increasing , decreasing и constant :

 s1, s2 = df['a'].shift(), df['a'].shift(-1)

m1 = df['a'].gt(s1) | df['a'].lt(s2)
m2 = df['a'].lt(s1) | df['a'].gt(s2)
m3 = df['a'].eq(s1) | df['a'].eq(s2)

incr, decr, const = df[m1], df[m2], df[m3]
  

Результат:

 print(incr)
   a  b  c  d  e  f  g
0  1  1  1  2  1  2  1
1  2  3  2  1  2  1  2
2  3  1  3  1  3  1  2

print(decr)
   a  b  c  d  e  f  g
4  3  1  3  4  2  1  4
5  2  1  2  3  4  2  1
6  1  2  3  4  5  3  1

print(const)
   a  b  c  d  e  f  g
2  3  1  3  1  3  1  2
3  3  2  1  3  4  1  3
4  3  1  3  4  2  1  4