#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