У меня есть пандас dataframe, который имеет одну строку на объект. Внутри этого объекта есть подобъекты. Я хочу создать фрейм данных, который содержит одну строку на подобъект.

Я прочитал материал на расплаве, но не могу понять, как использовать его для того, что я хочу сделать.

Я хочу уйти от

ObjectID    Sub1_ID Sub1_Var1   Sub1_Var2   Sub1_Var3   Sub2_ID Sub2_Var1   Sub2_Var2   Sub2_Var3
1           98398   3           10          9           19231           6           7           5
2           87868   8           5           4               
3           4579    5           6           6           24833           6           2           2
4           2514    1           6           9   

Кому

ObjectID    Sub_ID  Var1    Var2    Var3
1           98398   3       10      9
1           19231   6       7       5
2           87868   8       5       4
3           4579    5       6       6
3           24833   6       2       2
4           2514    1       6       9
2
Richard Kapustynskyj 26 Июн 2019 в 18:41

3 ответа

Лучший ответ

Один из способов сделать это - использовать MultiIndex с from_arrays, а затем использовать stack для изменения формы фрейма данных:

df1 = df.set_index('ObjectID')

df1.columns = pd.MultiIndex.from_arrays(zip(*df1.columns.str.split('_')))

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

Выход:

   ObjectID       ID  Var1  Var2  Var3
0         1  98398.0   3.0  10.0   9.0
1         1  19231.0   6.0   7.0   5.0
2         2  87868.0   8.0   5.0   4.0
3         3   4579.0   5.0   6.0   6.0
4         3  24833.0   6.0   2.0   2.0
5         4   2514.0   1.0   6.0   9.0
10
Scott Boston 26 Июн 2019 в 18:04

Другой способ будет:

  1. Разделите ваш фрейм данных по столбцу Sub_ID на два разных фрейма данных
  2. Переименуйте столбцы обычным способом, splitting их в _
  3. Конкатировать кадры данных через axis=0 (друг на друга)
d1 = df.set_index('ObjectID').loc[:, 'Sub1_ID':'Sub1_Var3']
d2 = df.set_index('ObjectID').loc[:, 'Sub2_ID':]

d1.columns = d1.columns.str.split('_').str[1]
d2.columns = d2.columns.str.split('_').str[1]

pd.concat([d1, d2[d2['ID'].ne(0)]]).sort_index().reset_index()

   ObjectID     ID  Var1  Var2  Var3
0         1  98398     3    10     9
1         1  19231     6     7     5
2         2  87868     8     5     4
3         3   4579     5     6     6
4         3  24833     6     2     2
5         4   2514     1     6     9
0
Erfan 26 Июн 2019 в 16:32

Вы можете объединить подкадры данных:

def ren_col(x):
    if x.startswith('Obj'): return x
    elif x.endswith('ID'): return 'Sub_ID'
    else: return x[-4:]

cols = df.columns    
resul = pd.concat([df[sub].rename(ren_col, axis=1).dropna()
                   for sub in [[cols[0]] + cols[i:i+4].tolist()
                               for i in range(1, len(cols), 4)]]
                  ).sort_values(['ObjectID', 'Sub_ID']).reset_index(drop=True)

Это дает, как и ожидалось:

   ObjectID   Sub_ID  Var1  Var2  Var3
0         1  19231.0   6.0   7.0   5.0
1         1  98398.0   3.0  10.0   9.0
2         2  87868.0   8.0   5.0   4.0
3         3   4579.0   5.0   6.0   6.0
4         3  24833.0   6.0   2.0   2.0
5         4   2514.0   1.0   6.0   9.0
0
Serge Ballesta 26 Июн 2019 в 16:18