strings - python dataframe concat columns
¿Para qué sirven los argumentos de ''niveles'', ''claves'' y nombres en la función concat de Pandas? (1)
En el proceso de responder esta pregunta por mí mismo, aprendí muchas cosas y quería armar un catálogo de ejemplos y algunas explicaciones.
La respuesta específica al punto del argumento de los
levels
llegará al final.
pandas.concat
: el manual que falta
Enlace a la documentación actual
Importaciones y objetos definitorios
import pandas as pd
d1 = pd.DataFrame(dict(A=.1, B=.2, C=.3), index=[2, 3])
d2 = pd.DataFrame(dict(B=.4, C=.5, D=.6), index=[1, 2])
d3 = pd.DataFrame(dict(A=.7, B=.8, D=.9), index=[1, 3])
s1 = pd.Series([1, 2], index=[2, 3])
s2 = pd.Series([3, 4], index=[1, 2])
s3 = pd.Series([5, 6], index=[1, 3])
Argumentos
objs
El primer argumento que encontramos es
objs
:
objs : una secuencia o mapeo de objetos Series, DataFrame o Panel Si se pasa un dict, las claves ordenadas se utilizarán como argumento de claves, a menos que se pase, en cuyo caso se seleccionarán los valores (ver más abajo). Cualquier objeto None se eliminará en silencio a menos que todos sean None, en cuyo caso se generará un ValueError
-
Normalmente vemos esto usado con una lista de objetos
Series
oDataFrame
. -
dict
quedict
puede ser muy útil. -
Los generadores también se pueden usar y pueden ser útiles cuando se usa el
map
como en elmap(f, list_of_df)
Por ahora, seguiremos con una lista de algunos de los objetos
DataFrame
y
Series
definidos anteriormente.
MultiIndex
cómo se pueden aprovechar los diccionarios para dar resultados
MultiIndex
muy útiles
MultiIndex
adelante.
pd.concat([d1, d2])
A B C D
2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
axis
El segundo argumento que encontramos es el
axis
cuyo valor predeterminado es
0
:
eje : {0 / ''índice'', 1 / ''columnas''}, predeterminado 0 El eje para concatenar.
Dos
DataFrame
s con
axis=0
(apilado)
Para valores de
0
o
index
queremos decir: "Alinear a lo largo de las columnas y agregar al índice".
Como se muestra arriba, donde usamos
axis=0
, porque
0
es el valor predeterminado, y vemos que el índice de
d2
extiende el índice de
d1
pesar de la superposición del valor
2
:
pd.concat([d1, d2], axis=0)
A B C D
2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
Dos
DataFrame
s con
axis=1
(lado a lado)
Para los valores
1
o
columns
queremos decir: "Alinear a lo largo del índice y agregar a las columnas",
pd.concat([d1, d2], axis=1)
A B C B C D
1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN
Podemos ver que el índice resultante es la unión de índices y las columnas resultantes son la extensión de columnas de
d1
por las columnas de
d2
.
Dos (o tres)
Series
con
axis=0
(apiladas)
Al combinar
pandas.Series
largo del
axis=0
, obtenemos un
pandas.Series
.
El nombre de la
Series
resultante será
None
menos que todas las
Series
combinadas tengan el mismo nombre.
Preste atención al
''Name: A''
cuando imprimamos la
Series
resultante.
Cuando no está presente, podemos suponer que el nombre de la
Series
es
None
.
| | | pd.concat(
| pd.concat( | pd.concat( | [s1.rename(''A''),
pd.concat( | [s1.rename(''A''), | [s1.rename(''A''), | s2.rename(''B''),
[s1, s2]) | s2]) | s2.rename(''A'')]) | s3.rename(''A'')])
-------------- | --------------------- | ---------------------- | ----------------------
2 1 | 2 1 | 2 1 | 2 1
3 2 | 3 2 | 3 2 | 3 2
1 3 | 1 3 | 1 3 | 1 3
2 4 | 2 4 | 2 4 | 2 4
dtype: int64 | dtype: int64 | Name: A, dtype: int64 | 1 5
| | | 3 6
| | | dtype: int64
Dos (o tres)
Series
con
axis=1
(lado a lado)
Al combinar
pandas.Series
largo de
axis=1
, es el atributo de
name
que nos referimos para inferir el nombre de una columna en el
pandas.DataFrame
resultante.
| | pd.concat(
| pd.concat( | [s1.rename(''X''),
pd.concat( | [s1.rename(''X''), | s2.rename(''Y''),
[s1, s2], axis=1) | s2], axis=1) | s3.rename(''Z'')], axis=1)
---------------------- | --------------------- | ------------------------------
0 1 | X 0 | X Y Z
1 NaN 3.0 | 1 NaN 3.0 | 1 NaN 3.0 5.0
2 1.0 4.0 | 2 1.0 4.0 | 2 1.0 4.0 NaN
3 2.0 NaN | 3 2.0 NaN | 3 2.0 NaN 6.0
Series
mixtas y
DataFrame
con
axis=0
(apilado)
Cuando se realiza una concatenación de una
Series
y un
DataFrame
largo del
axis=0
, convertimos todas las
Series
en un
DataFrame
una sola columna.
Tenga especial en cuenta que esta es una concatenación a lo largo del
axis=0
;
eso significa extender el índice (filas) mientras se alinean las columnas.
En los ejemplos a continuación, vemos que el índice se convierte en
[2, 3, 2, 3]
que es un agregado indiscriminado de índices.
Las columnas no se superponen a menos que fuerce el nombre de la columna
Series
con el argumento
to_frame
:
pd.concat( |
[s1.to_frame(), d1]) | pd.concat([s1, d1])
------------------------- | ---------------------
0 A B C | 0 A B C
2 1.0 NaN NaN NaN | 2 1.0 NaN NaN NaN
3 2.0 NaN NaN NaN | 3 2.0 NaN NaN NaN
2 NaN 0.1 0.2 0.3 | 2 NaN 0.1 0.2 0.3
3 NaN 0.1 0.2 0.3 | 3 NaN 0.1 0.2 0.3
Puede ver que los resultados de
pd.concat([s1, d1])
son los mismos que si hubiera realizado
to_frame
mismo el
to_frame
.
Sin embargo, puedo controlar el nombre de la columna resultante con un parámetro a
to_frame
.
Cambiar el nombre de la
Series
con el método de
rename
no
controla el nombre de la columna en el
DataFrame
resultante.
# Effectively renames | |
# `s1` but does not align | # Does not rename. So | # Renames to something
# with columns in `d1` | # Pandas defaults to `0` | # that does align with `d1`
pd.concat( | pd.concat( | pd.concat(
[s1.to_frame(''X''), d1]) | [s1.rename(''X''), d1]) | [s1.to_frame(''B''), d1])
---------------------------- | -------------------------- | ----------------------------
A B C X | 0 A B C | A B C
2 NaN NaN NaN 1.0 | 2 1.0 NaN NaN NaN | 2 NaN 1.0 NaN
3 NaN NaN NaN 2.0 | 3 2.0 NaN NaN NaN | 3 NaN 2.0 NaN
2 0.1 0.2 0.3 NaN | 2 NaN 0.1 0.2 0.3 | 2 0.1 0.2 0.3
3 0.1 0.2 0.3 NaN | 3 NaN 0.1 0.2 0.3 | 3 0.1 0.2 0.3
Series
mixtas y
DataFrame
con
axis=1
(lado a lado)
Esto es bastante intuitivo.
Series
nombre de la columna
Series
se predetermina a una enumeración de dichos objetos
Series
cuando un atributo de
name
no está disponible.
| pd.concat(
pd.concat( | [s1.rename(''X''),
[s1, d1], | s2, s3, d1],
axis=1) | axis=1)
------------------- | -------------------------------
0 A B C | X 0 1 A B C
2 1 0.1 0.2 0.3 | 1 NaN 3.0 5.0 NaN NaN NaN
3 2 0.1 0.2 0.3 | 2 1.0 4.0 NaN 0.1 0.2 0.3
| 3 2.0 NaN 6.0 0.1 0.2 0.3
join
El tercer argumento es
join
que describe si la fusión resultante debería ser una fusión externa (por defecto) o una fusión interna.
unirse : {''interno'', ''externo''}, predeterminado ''externo''
Cómo manejar índices en otros ejes.
Resulta que no hay una opción
left
o
right
, ya que
pd.concat
puede manejar más de dos objetos para fusionar.
En el caso de
d1
y
d2
, las opciones se ven así:
outer
pd.concat([d1, d2], axis=1, join=''outer'')
A B C B C D
1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN
inner
pd.concat([d1, d2], axis=1, join=''inner'')
A B C B C D
2 0.1 0.2 0.3 0.4 0.5 0.6
join_axes
El cuarto argumento es lo que nos permite hacer nuestra fusión
left
y más.
join_axes : lista de objetos Index
Índices específicos a utilizar para los otros ejes n - 1 en lugar de realizar la lógica de conjunto interno / externo.
Combinación izquierda
pd.concat([d1, d2, d3], axis=1, join_axes=[d1.index])
A B C B C D A B D
2 0.1 0.2 0.3 0.4 0.5 0.6 NaN NaN NaN
3 0.1 0.2 0.3 NaN NaN NaN 0.7 0.8 0.9
Fusión correcta
pd.concat([d1, d2, d3], axis=1, join_axes=[d3.index])
A B C B C D A B D
1 NaN NaN NaN 0.4 0.5 0.6 0.7 0.8 0.9
3 0.1 0.2 0.3 NaN NaN NaN 0.7 0.8 0.9
ignore_index
ignore_index : boolean, por defecto False
Si es verdadero, no use los valores de índice a lo largo del eje de concatenación. El eje resultante se etiquetará como 0, ..., n - 1. Esto es útil si está concatenando objetos donde el eje de concatenación no tiene información de indexación significativa. Tenga en cuenta que los valores de índice en los otros ejes aún se respetan en la unión.
Al igual que cuando apilo
d1
sobre
d2
, si no me importan los valores del índice, podría restablecerlos o ignorarlos.
| pd.concat( | pd.concat(
| [d1, d2], | [d1, d2]
pd.concat([d1, d2]) | ignore_index=True) | ).reset_index(drop=True)
--------------------- | ----------------------- | -------------------------
A B C D | A B C D | A B C D
2 0.1 0.2 0.3 NaN | 0 0.1 0.2 0.3 NaN | 0 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN | 1 0.1 0.2 0.3 NaN | 1 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6 | 2 NaN 0.4 0.5 0.6 | 2 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6 | 3 NaN 0.4 0.5 0.6 | 3 NaN 0.4 0.5 0.6
Y cuando se usa
axis=1
:
| pd.concat(
| [d1, d2], axis=1,
pd.concat([d1, d2], axis=1) | ignore_index=True)
------------------------------- | -------------------------------
A B C B C D | 0 1 2 3 4 5
1 NaN NaN NaN 0.4 0.5 0.6 | 1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6 | 2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN | 3 0.1 0.2 0.3 NaN NaN NaN
keys
Podemos pasar una lista de valores escalares o tuplas para asignar valores tuples o escalares al MultiIndex correspondiente. La longitud de la lista aprobada debe ser la misma que la cantidad de elementos que se concatenan.
teclas : secuencia, por defecto Ninguno
Si pasaron varios niveles, deberían contener tuplas. Construya el índice jerárquico usando las claves pasadas como el nivel más externo
axis=0
Al concatenar objetos
Series
largo del
axis=0
(extendiendo el índice).
Esas claves se convierten en un nuevo nivel inicial de un objeto
MultiIndex
en el atributo de índice.
# length 3 length 3 # length 2 length 2
# /--------/ /-----------/ # /----/ /------/
pd.concat([s1, s2, s3], keys=[''A'', ''B'', ''C'']) pd.concat([s1, s2], keys=[''A'', ''B''])
---------------------------------------------- -------------------------------------
A 2 1 A 2 1
3 2 3 2
B 1 3 B 1 3
2 4 2 4
C 1 5 dtype: int64
3 6
dtype: int64
Sin embargo, podemos usar más que valores escalares en el argumento de
keys
para crear un
MultiIndex
aún más
MultiIndex
.
Aquí pasamos
tuples
de longitud 2 antepuestas a dos nuevos niveles de un
MultiIndex
:
pd.concat(
[s1, s2, s3],
keys=[(''A'', ''X''), (''A'', ''Y''), (''B'', ''X'')])
-----------------------------------------------
A X 2 1
3 2
Y 1 3
2 4
B X 1 5
3 6
dtype: int64
axis=1
Es un poco diferente cuando se extiende a lo largo de las columnas.
Cuando usamos
axis=0
(ver arriba) nuestras
keys
actuaban como niveles de
MultiIndex
además del índice existente.
Para
axis=1
, nos estamos refiriendo a un eje que los objetos
Series
no tienen, es decir, el atributo de
columns
.
Series
axis=1
Observe que nombrar
s1
y
s2
importante siempre que no se pasen
keys
, pero se anula si se pasan
keys
.
| | | pd.concat(
| pd.concat( | pd.concat( | [s1.rename(''U''),
pd.concat( | [s1, s2], | [s1.rename(''U''), | s2.rename(''V'')],
[s1, s2], | axis=1, | s2.rename(''V'')], | axis=1,
axis=1) | keys=[''X'', ''Y'']) | axis=1) | keys=[''X'', ''Y''])
-------------- | --------------------- | ---------------------- | ----------------------
0 1 | X Y | U V | X Y
1 NaN 3.0 | 1 NaN 3.0 | 1 NaN 3.0 | 1 NaN 3.0
2 1.0 4.0 | 2 1.0 4.0 | 2 1.0 4.0 | 2 1.0 4.0
3 2.0 NaN | 3 2.0 NaN | 3 2.0 NaN | 3 2.0 NaN
MultiIndex
con
Series
y
axis=1
pd.concat(
[s1, s2],
axis=1,
keys=[(''W'', ''X''), (''W'', ''Y'')])
-----------------------------------
W
X Y
1 NaN 3.0
2 1.0 4.0
3 2.0 NaN
Dos
DataFrame
con
axis=1
Al igual que con los ejemplos
axis=0
, las
keys
agregan niveles a un
MultiIndex
, pero esta vez al objeto almacenado en el atributo de
columns
.
pd.concat( | pd.concat(
[d1, d2], | [d1, d2],
axis=1, | axis=1,
keys=[''X'', ''Y'']) | keys=[(''First'', ''X''), (''Second'', ''X'')])
------------------------------- | --------------------------------------------
X Y | First Second
A B C B C D | X X
1 NaN NaN NaN 0.4 0.5 0.6 | A B C B C D
2 0.1 0.2 0.3 0.4 0.5 0.6 | 1 NaN NaN NaN 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN | 2 0.1 0.2 0.3 0.4 0.5 0.6
| 3 0.1 0.2 0.3 NaN NaN NaN
Series
y
DataFrame
con
axis=1
Esto es complicado
En este caso, un valor de clave escalar no puede actuar como el único nivel de índice para el objeto
Series
cuando se convierte en una columna mientras que también actúa como el primer nivel de un
MultiIndex
para el
DataFrame
.
Entonces, Pandas usará nuevamente el atributo de
name
del objeto
Series
como fuente del nombre de la columna.
pd.concat( | pd.concat(
[s1, d1], | [s1.rename(''Z''), d1],
axis=1, | axis=1,
keys=[''X'', ''Y'']) | keys=[''X'', ''Y''])
--------------------- | --------------------------
X Y | X Y
0 A B C | Z A B C
2 1 0.1 0.2 0.3 | 2 1 0.1 0.2 0.3
3 2 0.1 0.2 0.3 | 3 2 0.1 0.2 0.3
Limitaciones de
keys
e
MultiIndex
MultiIndex.
Pandas solo parece inferir nombres de columna a partir del nombre de la
Series
, pero no completará los espacios en blanco cuando se realiza una concatenación análoga entre marcos de datos con un número diferente de niveles de columna.
d1_ = pd.concat(
[d1], axis=1,
keys=[''One''])
d1_
One
A B C
2 0.1 0.2 0.3
3 0.1 0.2 0.3
Luego concatene esto con otro marco de datos con solo un nivel en el objeto de columnas y Pandas se negará a intentar hacer tuplas del objeto
MultiIndex
y combinará todos los marcos de datos como si fuera un solo nivel de objetos, escalares y tuplas.
pd.concat([d1_, d2], axis=1)
(One, A) (One, B) (One, C) B C D
1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN
Pasar un
dict
lugar de una
list
Al pasar un diccionario,
pandas.concat
usará las claves del diccionario como parámetro de
keys
.
# axis=0 | # axis=1
pd.concat( | pd.concat(
{0: d1, 1: d2}) | {0: d1, 1: d2}, axis=1)
----------------------- | -------------------------------
A B C D | 0 1
0 2 0.1 0.2 0.3 NaN | A B C B C D
3 0.1 0.2 0.3 NaN | 1 NaN NaN NaN 0.4 0.5 0.6
1 1 NaN 0.4 0.5 0.6 | 2 0.1 0.2 0.3 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6 | 3 0.1 0.2 0.3 NaN NaN NaN
levels
Esto se usa junto con el argumento de las
keys
Cuando los
levels
se dejan como su valor predeterminado de
None
, Pandas tomará los valores únicos de cada nivel del
MultiIndex
resultante y lo usará como el objeto usado en el atributo
index.levels
resultante.
niveles : lista de secuencias, por defecto Ninguno
Niveles específicos (valores únicos) a utilizar para construir un MultiIndex. De lo contrario, se deducirán de las teclas.
Si Pandas ya infiere cuáles deberían ser estos niveles, ¿qué ventaja hay para especificarlo nosotros mismos? Mostraré un ejemplo y dejaré que pienses en otras razones por las cuales esto podría ser útil.
Ejemplo
Según la documentación, el argumento de
levels
es una lista de secuencias.
Esto significa que podemos usar otros
pandas.Index
como una de esas secuencias.
Considere el marco de datos
df
que es la concatenación de
d1
,
d2
y
d3
:
df = pd.concat(
[d1, d2, d3], axis=1,
keys=[''First'', ''Second'', ''Fourth''])
df
First Second Fourth
A B C B C D A B D
1 NaN NaN NaN 0.4 0.5 0.6 0.7 0.8 0.9
2 0.1 0.2 0.3 0.4 0.5 0.6 NaN NaN NaN
3 0.1 0.2 0.3 NaN NaN NaN 0.7 0.8 0.9
Los niveles del objeto de columnas son:
print(df, *df.columns.levels, sep=''/n'')
Index([''First'', ''Second'', ''Fourth''], dtype=''object'')
Index([''A'', ''B'', ''C'', ''D''], dtype=''object'')
Si usamos la
sum
dentro de un
groupby
, obtenemos:
df.groupby(axis=1, level=0).sum()
First Fourth Second
1 0.0 2.4 1.5
2 0.6 0.0 1.5
3 0.6 2.4 0.0
Pero, ¿qué pasaría si en lugar de
[''First'', ''Second'', ''Fourth'']
hubiera otras categorías faltantes llamadas
Third
y
Fifth
?
¿Y quería que se incluyeran en los resultados de un
groupby
agregación?
Podemos hacer esto si tuviéramos
pandas.CategoricalIndex
.
Y podemos especificar eso de antemano con el argumento de
levels
.
Entonces, en su lugar, definamos
df
como:
cats = [''First'', ''Second'', ''Third'', ''Fourth'', ''Fifth'']
lvl = pd.CategoricalIndex(cats, categories=cats, ordered=True)
df = pd.concat(
[d1, d2, d3], axis=1,
keys=[''First'', ''Second'', ''Fourth''],
levels=[lvl]
)
df
First Fourth Second
1 0.0 2.4 1.5
2 0.6 0.0 1.5
3 0.6 2.4 0.0
Pero el primer nivel del objeto de columnas es:
df.columns.levels[0]
CategoricalIndex(
[''First'', ''Second'', ''Third'', ''Fourth'', ''Fifth''],
categories=[''First'', ''Second'', ''Third'', ''Fourth'', ''Fifth''],
ordered=True, dtype=''category'')
Y nuestro resumen
groupby
ve así:
df.groupby(axis=1, level=0).sum()
First Second Third Fourth Fifth
1 0.0 1.5 0.0 2.4 0.0
2 0.6 1.5 0.0 0.0 0.0
3 0.6 0.0 0.0 2.4 0.0
names
Esto se usa para nombrar los niveles de un
MultiIndex
resultante.
La longitud de la lista de
names
debe coincidir con el número de niveles en el
MultiIndex
resultante.
nombres : lista, predeterminado Ninguno
Nombres para los niveles en el índice jerárquico resultante
# axis=0 | # axis=1
pd.concat( | pd.concat(
[d1, d2], | [d1, d2],
keys=[0, 1], | axis=1, keys=[0, 1],
names=[''lvl0'', ''lvl1'']) | names=[''lvl0'', ''lvl1''])
----------------------------- | ----------------------------------
A B C D | lvl0 0 1
lvl0 lvl1 | lvl1 A B C B C D
0 2 0.1 0.2 0.3 NaN | 1 NaN NaN NaN 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN | 2 0.1 0.2 0.3 0.4 0.5 0.6
1 1 NaN 0.4 0.5 0.6 | 3 0.1 0.2 0.3 NaN NaN NaN
2 NaN 0.4 0.5 0.6 |
verify_integrity
Documentación autoexplicativa
understand_integrity : boolean, por defecto False
Compruebe si el nuevo eje concatenado contiene duplicados. Esto puede ser muy costoso en relación con la concatenación de datos real.
Debido a que el índice resultante de concatenar
d1
y
d2
no es único, fallará la verificación de integridad.
pd.concat([d1, d2])
A B C D
2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
Y
pd.concat([d1, d2], verify_integrity=True)
> ValueError: los índices tienen valores superpuestos: [2]
Preguntas
-
¿Cómo uso
pd.concat
? -
¿Para qué sirve el argumento de los
levels
? -
¿Para qué sirve el argumento de las
keys
? - ¿Hay algunos ejemplos para ayudar a explicar cómo usar todos los argumentos?
La función
concat
Pandas es la
navaja suiza
de las empresas de servicios públicos fusionadas.
La variedad de situaciones en las que es útil son numerosas.
La documentación existente deja de lado algunos detalles sobre algunos de los argumentos opcionales.
Entre ellos están los
levels
y argumentos
keys
.
Me propuse averiguar qué hacen esos argumentos.
pd.concat
una pregunta que actuará como puerta de entrada a muchos aspectos de
pd.concat
.
Considere los marcos de datos
d1
,
d2
y
d3
:
import pandas as pd
d1 = pd.DataFrame(dict(A=.1, B=.2, C=.3), [2, 3])
d2 = pd.DataFrame(dict(B=.4, C=.5, D=.6), [1, 2])
d3 = pd.DataFrame(dict(A=.7, B=.8, D=.9), [1, 3])
Si tuviera que concatenar esto junto con
pd.concat([d1, d2, d3], keys=[''d1'', ''d2'', ''d3''])
Obtengo el resultado esperado con un
pandas.MultiIndex
para mi objeto de
columns
:
A B C D
d1 2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
d2 1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
d3 1 0.7 0.8 NaN 0.9
3 0.7 0.8 NaN 0.9
Sin embargo, quería usar la
documentación de argumentación de
levels
:
niveles : lista de secuencias, por defecto Ninguno. Niveles específicos (valores únicos) a utilizar para construir un MultiIndex. De lo contrario, se deducirán de las teclas.
Entonces pasé
pd.concat([d1, d2, d3], keys=[''d1'', ''d2'', ''d3''], levels=[[''d1'', ''d2'']])
Y consigue un
KeyError
ValueError: Key d3 not in level Index([''d1'', ''d2''], dtype=''object'')
Esto tiene sentido. Los niveles que pasé fueron inadecuados para describir los niveles necesarios indicados por las teclas. Si no hubiera pasado nada, como hice anteriormente, los niveles se infieren (como se indica en la documentación). Pero, ¿de qué otra manera puedo usar este argumento para tener un mejor efecto?
Si probé esto en su lugar:
pd.concat([d1, d2, d3], keys=[''d1'', ''d2'', ''d3''], levels=[[''d1'', ''d2'', ''d3'']])
Yo y obtuve los mismos resultados que arriba. Pero cuando agrego un valor más a los niveles,
df = pd.concat([d1, d2, d3], keys=[''d1'', ''d2'', ''d3''], levels=[[''d1'', ''d2'', ''d3'', ''d4'']])
MultiIndex
con el mismo marco de datos de aspecto, pero el
MultiIndex
resultante tiene un nivel no utilizado.
df.index.levels[0]
Index([''d1'', ''d2'', ''d3'', ''d4''], dtype=''object'')
Entonces, ¿cuál es el punto del argumento de
level
y debería usar las
keys
diferente?
Estoy usando Python 3.6 y Pandas 0.22.