В pandas, как переупорядочить фрейм данных для одновременного объединения групп столбцов? - PullRequest
1 голос
/ 14 июля 2020

Надеюсь, кто-нибудь поможет мне решить мою проблему.

Учитывая фрейм данных pandas, как показано на изображении ниже,

enter image description here

I would like to re-arrange it into a new dataframe, combining several sets of columns (the sets have all the same size) such that each set becomes a single column as shown in the desired result image below.

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

Заранее благодарим за любые советы.

Ответы [ 3 ]

1 голос
/ 14 июля 2020

Для решения general вы можете попробовать один из следующих двух вариантов:

Вы можете попробовать это, используя OrderedDict, чтобы получить alpha-nonnumeri c имена столбцов упорядочены в алфавитном порядке, pd.DataFrame.filter для фильтрации столбцов с похожими именами, а затем объединить значения с pd.DataFrame.stack:

import pandas as pd
from collections import OrderedDict

df = pd.DataFrame([[0,1,2,3,4],[5,6,7,8,9]], columns=['a1','a2','b1','b2','c'])


newdf=pd.DataFrame()

for col in list(OrderedDict.fromkeys( ''.join(df.columns)).keys()):
    if col.isalpha():
        newdf[col]=df.filter(like=col, axis=1).stack().reset_index(level=1,drop=True)
newdf=newdf.reset_index(drop=True)

Выход:

df
   a1  a2  b1  b2  c
0   0   1   2   3  4
1   5   6   7   8  9

newdf
   a  b  c
0  0  2  4
1  1  3  4
2  5  7  9
3  6  8  9

Другой способ получить имена столбцов - использовать re и set, как здесь, а затем отсортировать столбцы в алфавитном порядке:

newdf=pd.DataFrame()
import re
for col in set(re.findall('[^\W\d_]',''.join(df.columns))):
    newdf[col]=df.filter(like=col, axis=1).stack().reset_index(level=1,drop=True)
newdf=newdf.reindex(sorted(newdf.columns), axis=1).reset_index(drop=True)

Вывод:

newdf
   a  b  c
0  0  2  4
1  1  3  4
2  5  7  9
3  6  8  9
0 голосов
/ 14 июля 2020

Вы можете сделать это с помощью pd.wide_to_long и rename столбца 'c':

df_out = pd.wide_to_long(df.reset_index().rename(columns={'c':'c1'}),
                         ['a','b','c'],'index','no')
df_out = df_out.reset_index(drop=True).ffill().astype(int)
df_out

Вывод:

   a  b  c
0  0  2  4
1  1  3  4
2  5  7  9
3  6  8  9

Тот же фрейм данных, только сортировка отличается.

pd.wide_to_long(df,  ['a','b'], 'c', 'no').reset_index().drop('no', axis=1)

Вывод:

   c  a  b
0  4  0  2
1  9  5  7
2  4  1  3
3  9  6  8
0 голосов
/ 14 июля 2020

Тот факт, что столбец c имел только один столбец, в отличие от других букв, имеющих два столбца, усложнял задачу. Сначала я сложил фрейм данных и избавился от чисел в именах столбцов. Затем для a и b я повернул фрейм данных и удалил все nans. Для c я умножил длину фрейма данных на 2, чтобы он соответствовал a и b, а затем объединил его с a и b.

input:

import pandas as pd
df = pd.DataFrame({'a1': {0: 0, 1: 5},
 'a2': {0: 1, 1: 6},
 'b1': {0: 2, 1: 7},
 'b2': {0: 3, 1: 8},
 'c': {0: 4, 1: 9}})
df

code:

df1=df.copy().stack().reset_index().replace('[0-9]+', '', regex=True)
dfab = df1[df1['level_1'].isin(['a','b'])].pivot(index=0, columns='level_1', values=0) \
                         .apply(lambda x: pd.Series(x.dropna().values)).astype(int)
dfc = pd.DataFrame(np.repeat(df['c'].values,2,axis=0)).rename({0:'c'}, axis=1)
df2=pd.merge(dfab, dfc, how='left', left_index=True, right_index=True)
df2

вывод:

    a   b   c
0   0   2   4
1   1   3   4
2   5   7   9
3   6   8   9
...