Вот общий код, представляющий то, что происходит в моем скрипте:

import pandas as pd
import numpy as np

dic = {}

for i in np.arange(0,10):
    dic[str(i)] = df = pd.DataFrame(np.random.randint(0,1000,size=(5000, 20)), 
                                    columns=list('ABCDEFGHIJKLMNOPQRST'))
    
df_out = pd.DataFrame(index = df.index)

for i in np.arange(0,10):
    df_out['A_'+str(i)] = dic[str(i)]['A'].astype('int')
    df_out['D_'+str(i)] = dic[str(i)]['D'].astype('int')
    df_out['H_'+str(i)] = dic[str(i)]['H'].astype('int')
    df_out['I_'+str(i)] = dic[str(i)]['I'].astype('int')
    df_out['M_'+str(i)] = dic[str(i)]['M'].astype('int')
    df_out['O_'+str(i)] = dic[str(i)]['O'].astype('int')
    df_out['Q_'+str(i)] = dic[str(i)]['Q'].astype('int')
    df_out['R_'+str(i)] = dic[str(i)]['R'].astype('int')
    df_out['S_'+str(i)] = dic[str(i)]['S'].astype('int')
    df_out['T_'+str(i)] = dic[str(i)]['T'].astype('int')
    df_out['C_'+str(i)] = dic[str(i)]['C'].astype('int')

Вы заметите, что как только число вставленных столбцов df_out (output) превысит 100, я получаю следующее предупреждение:

Предупреждение о производительности: DataFrame сильно фрагментирован. Обычно это результат многократного вызова frame.insert, что снижает производительность. Попробуйте вместо этого использовать pd.concat

Вопрос в том, как я могу использовать:

pd.concat()

И все еще есть настраиваемое имя столбца, которое зависит от ключа словаря?

ВАЖНО: я все же хотел бы сохранить выбор отдельных столбцов, а не все из них. Как в примере: A, D, H, I и т. Д.

Большое спасибо за вашу помощь !

2
plonfat 23 Ноя 2021 в 14:09

2 ответа

Лучший ответ

Используйте concat с плоским MultiIndex в map:

cols = ['A','D']
df_out = pd.concat({k: v[cols] for k, v in dic.items()}, axis=1).astype('int')
df_out.columns = df_out.columns.map(lambda x: f'{x[1]}_{x[0]}')

print (df_out)
   A_0  D_0  A_1  D_1  A_2  D_2  A_3  D_3
0  116  341  396  502  944  483  398  839
1  128  621  102   70  561  656   70  169
2  982   44  613  775  822  379  246   25
3  830  987  366  481  861  632  906  676
4  533  349  741  410  305  422  874   19
2
jezrael 23 Ноя 2021 в 14:32
Если я прав, ваш ответ предполагает, что все столбцы из всех dfs в словаре взяты. Я хотел бы взять только некоторые конкретные столбцы, но не все из них. По крайней мере, определенные столбцы, которые нужно выбрать, одинаковы для всех dfs в словаре.
 – 
plonfat
23 Ноя 2021 в 14:30
Допустим, я хотел бы иметь только A и D, поэтому результаты будут иметь следующие столбцы: A_0 D_0, A_1 D_1, A_2 D_2, A_3 D_3,
 – 
plonfat
23 Ноя 2021 в 14:32
- добавил в ответ.
 – 
jezrael
23 Ноя 2021 в 14:33
1
Есть идеи, почему простой df ['new_col'] = col неэффективен? Мне так легче / легче писать ...
 – 
plonfat
23 Ноя 2021 в 14:42
- Итераций много, если мало, то идеально.
 – 
jezrael
23 Ноя 2021 в 14:42

Вы можете использовать понимание с pd.concat:

cols = ['A', 'D']
out = pd.concat([df[cols].add_prefix(f'{k}_') for k, df in dic.items()], axis=1) \
        .astype(int)
print(out)

# Output:
   0_A  0_D  1_A  1_D  2_A  2_D  3_A  3_D
0  116  341  396  502  944  483  398  839
1  128  621  102   70  561  656   70  169
2  982   44  613  775  822  379  246   25
3  830  987  366  481  861  632  906  676
4  533  349  741  410  305  422  874   19
3
Corralien 23 Ноя 2021 в 15:03
Также совершенно правильный ответ. К сожалению, я не могу принять оба варианта ...
 – 
plonfat
23 Ноя 2021 в 14:47
1
Не проблема. Важно то, что это работает для вас, даже если вы используете мое решение в конце :-P. ржу не могу
 – 
Corralien
23 Ноя 2021 в 14:49
Где мне добавить в ответ .astype ('int')? До / после add_prefix?
 – 
plonfat
23 Ноя 2021 в 15:02
Используйте его в конце pd.concat.
 – 
Corralien
23 Ноя 2021 в 15:04