Pd.wide_to_long в Python работает медленно

У меня есть фрейм данных с 55049 строками и 667 столбцами.

Пример структуры данных:


data = {
    'g1': [1],
    'g2': [2],
    'g3': [3],
    
    'st1_1': [1],
    'st1_2': [1],
    'st1_3': [1],
    'st1_4': [1],
    'st1_5': [5],
    'st1_6': [5],
    'st1_7': [5],
    'st1_8': [5],
    
    'st1_Next_1': [8],
    'st1_Next_2': [8],
    'st1_Next_3': [8],
    'st1_Next_4': [8],
    'st1_Next_5': [9],
    'st1_Next_6': [9],
    'st1_Next_7': [9],
    'st1_Next_8': [9],
    
    'st2_1': [2],
    'st2_2': [2],
    'st2_3': [2],
    'st2_4': [2],
    'st2_5': [2],
    'st2_6': [2],
    'st2_7': [2],
    'st2_8': [2],
    
    'ft_1': [1],
    'ft_2': [0],
    'ft_3': [1],
    'ft_4': [1],
    'ft_5': [1],
    'ft_6': [0],
    'ft_7': [0],
    'ft_8': [1]
}

df = pd.DataFrame(data)
print(df)

Чтобы получить желаемый результат, у меня есть следующий код, который я использую pd.wide_to_long

ilist = ['g1','g2','g3']
stublist = ['st1','st1_Next','st2','ft']

df_long = pd.wide_to_long(
      df.reset_index(),
      i=['index']+ilist ,
      stubnames= stublist,
      j='j', sep='_').reset_index()

df_long = df_long[df_long['ft']==1]

Приведенный выше код работает нормально и дает ожидаемые результаты.

Я выполнил это Wide_to_long, чтобы применить фильтр df_long[df_long['ft']==1]. это означает, что ft_1 необходимо применить для всех _1, ft_2 для всех _2..... и так для всех _8.

Проблема в том, что выполнение операции Wide_to_long заняло около 2 минут. Поскольку у меня более 800 исходных файлов, для обработки всего процесса требуется 1600 минут, что довольно много.

Я ищу любые альтернативные предложения по переносу данных.

Я пробовал это, но у меня не сработало, с большой разницей.

Как предложил @sammywemmy, я попробовал приведенный ниже код. Но вывод отсутствует st1_Next.


ilist = ['g1','g2','g3']
stublist = ['st1','st1_Next','st2','ft']


df_pvot = df.pivot_longer(index=ilist,names_to=stublist,names_pattern=stublist)
print(df_pvot)

В выводе отсутствуют st1_Next и объединение данных с помощью st1 вместо нового столбца.

Output:

    g1  g2  g3  st1  st2   ft
0    1   2   3    1  2.0  1.0
1    1   2   3    1  2.0  0.0
2    1   2   3    1  2.0  1.0
3    1   2   3    1  2.0  1.0
4    1   2   3    5  2.0  1.0
5    1   2   3    5  2.0  0.0
6    1   2   3    5  2.0  0.0
7    1   2   3    5  2.0  1.0
8    1   2   3    8  NaN  NaN
9    1   2   3    8  NaN  NaN
10   1   2   3    8  NaN  NaN
11   1   2   3    8  NaN  NaN
12   1   2   3    9  NaN  NaN
13   1   2   3    9  NaN  NaN
14   1   2   3    9  NaN  NaN
15   1   2   3    9  NaN  NaN

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
71
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Один из вариантов — использование Pivot_longer, где вы передаете новые имена заголовков в names_to и список регулярных выражений в names_pattern:

# pip install pyjanitor
import pandas as pd

df.pivot_longer(index=ilist,names_to=stublist,names_pattern=stublist)
   g1  g2  g3  st1  st2  ft
0   1   2   3    1    2   1
1   1   2   3    1    2   0
2   1   2   3    1    2   1
3   1   2   3    1    2   1
4   1   2   3    1    2   1
5   1   2   3    1    2   0
6   1   2   3    1    2   0
7   1   2   3    1    2   1

Другой вариант — изменение формы столбцов с последующим pd.stack:

reshaped = df.set_index(ilist)
reshaped.columns = reshaped.columns.str.split('_',expand=True).set_names([None,'drop'])
reshaped.stack(level='drop').droplevel('drop').reset_index()
   g1  g2  g3  st1  st2  ft
0   1   2   3    1    2   1
1   1   2   3    1    2   0
2   1   2   3    1    2   1
3   1   2   3    1    2   1
4   1   2   3    1    2   1
5   1   2   3    1    2   0
6   1   2   3    1    2   0
7   1   2   3    1    2   1

это ответ на обновленный вопрос: names_pattern опирается на регулярные выражения, а внутри pd.Series.str.contains и np.select используются для извлечения и сопряжения столбцов с регулярными выражениями. Таким образом, регулярные выражения должны быть правильно созданы, чтобы соответствовать столбцам:

# pip install pyjanitor
import pandas as pd
import janitor 

# note the inclusion of digits within the regexes
names_pattern = [r'st1_\d+',r'st1_Next',r'st2_\d+', 'ft']

df.pivot_longer(index=ilist,names_to=stublist,names_pattern=names_pattern)
   g1  g2  g3  st1  st1_Next  st2  ft
0   1   2   3    1         8    2   1
1   1   2   3    1         8    2   0
2   1   2   3    1         8    2   1
3   1   2   3    1         8    2   1
4   1   2   3    5         9    2   1
5   1   2   3    5         9    2   0
6   1   2   3    5         9    2   0
7   1   2   3    5         9    2   1

Вы можете повторить это, используя stack, на этот раз с помощью pd.Series.str.rsplit() и n=1.

reshaped = df.set_index(ilist)
reshaped.columns = (reshaped
                    .columns
                    .str
                    .rsplit('_',n=1,expand=True)
                    .set_names([None, 'drop'])
                   )

reshaped.stack(level='drop').droplevel('drop').reset_index()
   g1  g2  g3  st1  st1_Next  st2  ft
0   1   2   3    1         8    2   1
1   1   2   3    1         8    2   0
2   1   2   3    1         8    2   1
3   1   2   3    1         8    2   1
4   1   2   3    5         9    2   1
5   1   2   3    5         9    2   0
6   1   2   3    5         9    2   0
7   1   2   3    5         9    2   1

Если вы понимаете шаблон, который имеют ваши столбцы, и адаптируете к нему свой код, все будет в порядке.

qq: pyjanitor звонит siuba? Интересно, что функции R проникают в Python. Обратите внимание, что siuba содержит большинство функций R, а df.pivot_longer присутствует, но о нем мало кто знает. кажется pyjanitor это расширение библиотеки R janitor

Onyambu 13.03.2024 06:05

@sammywenny Я пробовал pd.pivot_longer довольно быстрее, но результат не совпал. Например, у меня есть два столбца st1_1 и st1_Next_1, и я ожидаю, что на выходе появятся два столбца, но st1_Next объединяется со st1_1. Выводится только один столбец st1 с 16 строками. Я обновил вопрос данными. Можете ли вы помочь мне, как точно сопоставить имена столбцов? Я попробовал names_sep='_'. не сработало

Roshan N 13.03.2024 07:42

@RoshanNuvvula сейчас посмотрю

sammywemmy 13.03.2024 08:02

Регулярные выражения являются жадными, поэтому вам придется создавать свои регулярные выражения соответствующим образом, чтобы они соответствовали. я обновлю

sammywemmy 13.03.2024 08:07

@Onyambu нет, он не вызывает siuba.да, pyjanitor - это версия R janitor на Python. да, pivot_longer вдохновлен функцией Pivot_longer из Tidyr и берет идеи как из функции Pivot_longer, так и из функции Melt из datatable.

sammywemmy 13.03.2024 08:42

@sammywemmy Я просто меняю names_pattern = list(map(lambda x: x +"_[0-9]+", stublist)) на это выражение, так как у меня более 200 столбцов, все работает нормально. Спасибо огромное, этот код сэкономил много времени

Roshan N 13.03.2024 09:47

Другие вопросы по теме