para - renombrar columnas dataframe python
Python Pandas: cómo aplanar un índice jerárquico en columnas (10)
Creo que la forma más fácil de hacerlo sería establecer las columnas en el nivel superior:
df.columns = df.columns.get_level_values(0)
Nota: si el nivel tiene un nombre, también puede acceder a él por este, en lugar de por 0.
.
Si desea combinar / join
su MultiIndex en un índice (suponiendo que solo tiene entradas de cadenas en sus columnas) , puede:
df.columns = ['' ''.join(col).strip() for col in df.columns.values]
Nota: debemos strip
el espacio en blanco para cuando no haya un segundo índice.
In [11]: ['' ''.join(col).strip() for col in df.columns.values]
Out[11]:
[''USAF'',
''WBAN'',
''day'',
''month'',
''s_CD sum'',
''s_CL sum'',
''s_CNT sum'',
''s_PC sum'',
''tempf amax'',
''tempf amin'',
''year'']
Tengo un marco de datos con un índice jerárquico en el eje 1 (columnas) (de una operación groupby.agg):
USAF WBAN year month day s_PC s_CL s_CD s_CNT tempf
sum sum sum sum amax amin
0 702730 26451 1993 1 1 1 0 12 13 30.92 24.98
1 702730 26451 1993 1 2 0 0 13 13 32.00 24.98
2 702730 26451 1993 1 3 1 10 2 13 23.00 6.98
3 702730 26451 1993 1 4 1 0 12 13 10.04 3.92
4 702730 26451 1993 1 5 3 0 10 13 19.94 10.94
Quiero aplanarlo para que se vea así (los nombres no son críticos, podría cambiar el nombre):
USAF WBAN year month day s_PC s_CL s_CD s_CNT tempf_amax tmpf_amin
0 702730 26451 1993 1 1 1 0 12 13 30.92 24.98
1 702730 26451 1993 1 2 0 0 13 13 32.00 24.98
2 702730 26451 1993 1 3 1 10 2 13 23.00 6.98
3 702730 26451 1993 1 4 1 0 12 13 10.04 3.92
4 702730 26451 1993 1 5 3 0 10 13 19.94 10.94
¿Cómo hago esto? (He intentado mucho, fue en vano).
Por una sugerencia, aquí está la cabeza en forma dict
{(''USAF'', ''''): {0: ''702730'',
1: ''702730'',
2: ''702730'',
3: ''702730'',
4: ''702730''},
(''WBAN'', ''''): {0: ''26451'', 1: ''26451'', 2: ''26451'', 3: ''26451'', 4: ''26451''},
(''day'', ''''): {0: 1, 1: 2, 2: 3, 3: 4, 4: 5},
(''month'', ''''): {0: 1, 1: 1, 2: 1, 3: 1, 4: 1},
(''s_CD'', ''sum''): {0: 12.0, 1: 13.0, 2: 2.0, 3: 12.0, 4: 10.0},
(''s_CL'', ''sum''): {0: 0.0, 1: 0.0, 2: 10.0, 3: 0.0, 4: 0.0},
(''s_CNT'', ''sum''): {0: 13.0, 1: 13.0, 2: 13.0, 3: 13.0, 4: 13.0},
(''s_PC'', ''sum''): {0: 1.0, 1: 0.0, 2: 1.0, 3: 1.0, 4: 3.0},
(''tempf'', ''amax''): {0: 30.920000000000002,
1: 32.0,
2: 23.0,
3: 10.039999999999999,
4: 19.939999999999998},
(''tempf'', ''amin''): {0: 24.98,
1: 24.98,
2: 6.9799999999999969,
3: 3.9199999999999982,
4: 10.940000000000001},
(''year'', ''''): {0: 1993, 1: 1993, 2: 1993, 3: 1993, 4: 1993}}
En caso de que desee tener un separador en el nombre entre niveles, esta función funciona bien.
def flattenHierarchicalCol(col,sep = ''_''):
if not type(col) is tuple:
return col
else:
new_col = ''''
for leveli,level in enumerate(col):
if not level == '''':
if not leveli == 0:
new_col += sep
new_col += level
return new_col
df.columns = df.columns.map(flattenHierarchicalCol)
La respuesta de Andy Hayden es ciertamente la manera más fácil: si quieres evitar las etiquetas de columnas duplicadas, necesitas ajustar un poco
In [34]: df
Out[34]:
USAF WBAN day month s_CD s_CL s_CNT s_PC tempf year
sum sum sum sum amax amin
0 702730 26451 1 1 12 0 13 1 30.92 24.98 1993
1 702730 26451 2 1 13 0 13 0 32.00 24.98 1993
2 702730 26451 3 1 2 10 13 1 23.00 6.98 1993
3 702730 26451 4 1 12 0 13 1 10.04 3.92 1993
4 702730 26451 5 1 10 0 13 3 19.94 10.94 1993
In [35]: mi = df.columns
In [36]: mi
Out[36]:
MultiIndex
[(USAF, ), (WBAN, ), (day, ), (month, ), (s_CD, sum), (s_CL, sum), (s_CNT, sum), (s_PC, sum), (tempf, amax), (tempf, amin), (year, )]
In [37]: mi.tolist()
Out[37]:
[(''USAF'', ''''),
(''WBAN'', ''''),
(''day'', ''''),
(''month'', ''''),
(''s_CD'', ''sum''),
(''s_CL'', ''sum''),
(''s_CNT'', ''sum''),
(''s_PC'', ''sum''),
(''tempf'', ''amax''),
(''tempf'', ''amin''),
(''year'', '''')]
In [38]: ind = pd.Index([e[0] + e[1] for e in mi.tolist()])
In [39]: ind
Out[39]: Index([USAF, WBAN, day, month, s_CDsum, s_CLsum, s_CNTsum, s_PCsum, tempfamax, tempfamin, year], dtype=object)
In [40]: df.columns = ind
In [46]: df
Out[46]:
USAF WBAN day month s_CDsum s_CLsum s_CNTsum s_PCsum tempfamax tempfamin /
0 702730 26451 1 1 12 0 13 1 30.92 24.98
1 702730 26451 2 1 13 0 13 0 32.00 24.98
2 702730 26451 3 1 2 10 13 1 23.00 6.98
3 702730 26451 4 1 12 0 13 1 10.04 3.92
4 702730 26451 5 1 10 0 13 3 19.94 10.94
year
0 1993
1 1993
2 1993
3 1993
4 1993
Siguiendo @jxstanford y @ tvt173, escribí una función rápida que debería hacer el truco, independientemente de los nombres de columna string / int:
def flatten_cols(df):
df.columns = [
''_''.join(tuple(map(str, t))).rstrip(''_'')
for t in df.columns.values
]
return df
También podría hacer lo siguiente. Considere df
para ser su marco de datos y asuma un índice de dos niveles (como es el caso en su ejemplo)
df.columns = [(df.columns[i][0])+''_''+(datadf_pos4.columns[i][1]) for i in range(len(df.columns))]
Un poco tarde quizás, pero si no te preocupan los nombres de columna duplicados:
df.columns = df.columns.tolist()
Una solución general que maneja múltiples niveles y tipos mixtos:
df.columns = [''_''.join(tuple(map(str, t))) for t in df.columns.values]
Y si desea retener cualquier información de agregación del segundo nivel del multiindex, puede intentar esto:
In [1]: new_cols = [''''.join(t) for t in df.columns]
Out[1]:
[''USAF'',
''WBAN'',
''day'',
''month'',
''s_CDsum'',
''s_CLsum'',
''s_CNTsum'',
''s_PCsum'',
''tempfamax'',
''tempfamin'',
''year'']
In [2]: df.columns = new_cols
df.columns = [''_''.join(tup).rstrip(''_'') for tup in df.columns.values]
pd.DataFrame(df.to_records()) # multiindex become columns and new index is integers only