Свернуть / транспонировать столбцы DataFrame на основе повторения - панды - PullRequest
0 голосов
/ 14 октября 2019

У меня есть фрейм данных sample_df вот так,

   id   pd  pd_dt      pd_tp    pd.1    pd_dt.1     pd_tp.1 pd.2    pd_dt.2     pd_tp.2
0  1    100 per year   468      200     per year    400     300     per year    320
1  2    100 per year   60       200     per year    890     300     per year    855

Мне нужен мой вывод вот так,

id pd   pd_dt     pd_tp
1  100  per year  468
1  200  per year  400
1  300  per year  320
2  100  per year  60
2  200  per year  890
2  300  per year  855

Я попробовал следующее,

sample_df.stack().reset_index().drop('level_1',axis=1)

Это не работает. У меня pd, pd_dt, pd_tp повторяются со значениями .1, .2 ...

У меня Как получить выход?

Ответы [ 3 ]

2 голосов
/ 14 октября 2019

Вы хотите pd.wide_to_long, но с некоторыми изменениями, так как ваши первые несколько столбцов не разделяют одинаковые шаблоны с остальными:

# rename
df.columns = [x+'.0' if '.' not in x and x != 'id' else x
                for x in df.columns]

pd.wide_to_long(df, stubnames=['pd','pd_dt','pd_tp'],
                i='id', j='order', sep='.')

Вывод:

           pd     pd_dt  pd_tp
id order                      
1  0      100  per year    468
2  0      100  per year     60
1  1      200  per year    400
2  1      200  per year    890
1  2      300  per year    320
2  2      300  per year    855
1 голос
/ 14 октября 2019

Вы можете использовать numpy split, чтобы разбить его на n массивов и объединить их обратно вместе. Затем повторите столбец id с количеством строк в новом кадре данных.

new_df = pd.DataFrame(np.concatenate(np.split(df.iloc[:,1:].values, (df.shape[1] - 1)/3, axis=1)))
new_df.columns = ['pd','pd_dt','pd_tp']
new_df['id'] = pd.concat([df.id] * (new_df.shape[0]//2), ignore_index=True)
new_df.sort_values('id')

Результат:

    pd     pd_dt pd_tp  id
0  100  per year   468   1
2  200  per year   400   1
4  300  per year   320   1
1  100  per year    60   2
3  200  per year   890   2
5  300  per year   855   2
1 голос
/ 14 октября 2019

Вы можете сделать это:

dt_mask=df.columns.str.contains('dt')
tp_mask=df.columns.str.contains('tp')
new_df=pd.DataFrame()
new_df['pd']=df[df.columns[~(dt_mask|tp_mask)]].stack().reset_index(level=1,drop='level_1')
new_df['pd_dt']=df[df.columns[dt_mask]].stack().reset_index(level=1,drop='level_1')
new_df['pd_tp']=df[df.columns[tp_mask]].stack().reset_index(level=1,drop='level_1')
new_df.reset_index(inplace=True)
print(new_df)

   id   pd     pd_dt  pd_tp
0   1  100  per_year    468
1   1  200  per_year    400
2   1  300  per_year    320
3   2  100  per_year     60
4   2  200  per_year    890
5   2  300  per_year    855
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...