index - pandas python
¿Hay alguna manera de copiar solo la estructura(no los datos) de un Pandas DataFrame? (7)
Comencemos con algunos datos de muestra
In [1]: import pandas as pd
In [2]: df = pd.DataFrame([[1, ''a''], [2, ''b''], [3, ''c'']],
...: columns=[''num'', ''char''])
In [3]: df
Out[3]:
num char
0 1 a
1 2 b
2 3 c
In [4]: df.dtypes
Out[4]:
num int64
char object
dtype: object
Ahora usemos una inicialización simple de DataFrame
utilizando las columnas del DataFrame
original pero sin proporcionar datos:
In [5]: empty_copy_1 = pd.DataFrame(data=None, columns=df.columns)
In [6]: empty_copy_1
Out[6]:
Empty DataFrame
Columns: [num, char]
Index: []
In [7]: empty_copy_1.dtypes
Out[7]:
num object
char object
dtype: object
Como puede ver, los tipos de datos de columna no son los mismos que en nuestro DataFrame
original.
Por lo tanto, si desea conservar el tipo de columna ...
Si desea conservar los tipos de datos de columna, necesita construir el DataFrame
una Series
a la vez
In [8]: empty_copy_2 = pd.DataFrame.from_items([
...: (name, pd.Series(data=None, dtype=series.dtype))
...: for name, series in df.iteritems()])
In [9]: empty_copy_2
Out[9]:
Empty DataFrame
Columns: [num, char]
Index: []
In [10]: empty_copy_2.dtypes
Out[10]:
num int64
char object
dtype: object
Recibí un DataFrame de algún lugar y quiero crear otro DataFrame con el mismo número y nombres de columnas y filas (índices). Por ejemplo, supongamos que el marco de datos original se creó como
import pandas as pd
df1 = pd.DataFrame([[11,12],[21,22]], columns=[''c1'',''c2''], index=[''i1'',''i2''])
Copié la estructura al definir explícitamente las columnas y los nombres:
df2 = pd.DataFrame(columns=df1.columns, index=df1.index)
No quiero copiar los datos; de lo contrario, podría simplemente escribir df2 = df1.copy()
. En otras palabras, después de crear df2, debe contener solo elementos NaN:
In [1]: df1
Out[1]:
c1 c2
i1 11 12
i2 21 22
In [2]: df2
Out[2]:
c1 c2
i1 NaN NaN
i2 NaN NaN
¿Hay una forma más idiomática de hacerlo?
En la versión 0.18 de pandas, el constructor de DataFrame no tiene opciones para crear un dataframe como otro dataframe con NaN en lugar de los valores.
El código que utiliza df2 = pd.DataFrame(columns=df1.columns, index=df1.index)
es la forma más lógica, la única forma de mejorarlo es deletrear aún más lo que está haciendo es agregar data=None
, para que otros codificadores vean directamente que intencionalmente omite los datos de este nuevo DataFrame que está creando.
TLDR: Entonces mi sugerencia es:
Explícito es mejor que implícito
df2 = pd.DataFrame(data=None, columns=df1.columns, index=df1.index)
Muy parecido al tuyo, pero más explicado.
Ese es un trabajo para reindex_like
. Comience con el original:
df1 = pd.DataFrame([[11, 12], [21, 22]], columns=[''c1'', ''c2''], index=[''i1'', ''i2''])
Construye un DataFrame vacío y reindexalo como df1:
pd.DataFrame().reindex_like(df1)
Out:
c1 c2
i1 NaN NaN
i2 NaN NaN
Esto me ha funcionado en pandas 0.22: df2 = pd.DataFrame(index=df.index.delete(slice(None)), columns=df.columns)
Convertir tipos: df2 = df2.astype(df.dtypes)
delete(slice(None))
En caso de que no desee mantener los valores de los índices.
Puede simplemente mask
por notna()
es decir
df1 = pd.DataFrame([[11, 12], [21, 22]], columns=[''c1'', ''c2''], index=[''i1'', ''i2''])
df2 = df1.mask(df1.notna())
c1 c2
i1 NaN NaN
i2 NaN NaN
Sé que esta es una vieja pregunta, pero pensé que agregaría mis dos centavos.
def df_cols_like(df):
"""
Returns an empty data frame with the same column names and types as df
"""
df2 = pd.DataFrame({i[0]: pd.Series(dtype=i[1])
for i in df.dtypes.iteritems()},
columns=df.dtypes.index)
return df2
Este enfoque se centra en el atributo df.dtypes
del marco de datos de entrada, df
, que es un pd.Series
. Un pd.DataFrame
se construye a partir de un diccionario de objetos pd.Series
vacíos nombrados utilizando los nombres de columna de entrada con el orden de columna tomado de la entrada df
.
Una alternativa simple: primero copie la estructura básica o los índices y columnas con el tipo de datos del dataframe original (df1) en df2
df2 = df1.iloc[0:0]
Luego llene su marco de datos con filas vacías: pseudocódigo que deberá adaptarse para que coincida mejor con su estructura real:
s = pd.Series([Nan,Nan,Nan], index=[''Col1'', ''Col2'', ''Col3''])
recorrer las filas en df1
df2 = df2.append(s)