Есть ли способ скопировать только структуру (а не данные) Pandas DataFrame?
Я откуда-то получил DataFrame и хочу создать еще один DataFrame с тем же числом и именами столбцов и строк (индексов). Например, предположим, что исходный фрейм данных был создан как
import pandas as pd
df1 = pd.DataFrame([[11,12],[21,22]], columns=['c1','c2'], index=['i1','i2'])
Я скопировал структуру, явно указав столбцы и имена:
df2 = pd.DataFrame(columns=df1.columns, index=df1.index)
Я не хочу копировать данные, иначе я мог бы просто написать df2 = df1.copy()
. Другими словами, после создания df2 он должен содержать только элементы 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
Есть ли более идиоматический способ сделать это?
Ответы
Ответ 1
Начнем с некоторых примеров данных
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
Теперь можно использовать простую инициализацию DataFrame
, используя столбцы исходного DataFrame
, но не предоставляя никаких данных:
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
Как вы можете видеть, типы данных столбцов не совпадают, как в исходном DataFrame
.
Итак, если вы хотите сохранить столбец dtype
...
Если вы хотите сохранить типы данных столбцов, вам нужно построить DataFrame
один Series
за раз
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
Ответ 2
В версия 0.18 из pandas конструктор DataFrame не имеет параметров для создания фрейма данных, например, другого блока данных с NaN вместо значений.
Код, который вы используете df2 = pd.DataFrame(columns=df1.columns, index=df1.index)
, является наиболее логичным способом, единственный способ улучшить его - еще раз указать, что вы делаете, это добавить data=None
, чтобы другие кодеры сразу видели, что вы намеренно уходите из данных нового созданного DataFrame.
TL;DR: Итак, мое предложение:
Явный лучше, чем неявный
df2 = pd.DataFrame(data=None, columns=df1.columns, index=df1.index)
Очень похож на ваш, но более подробно.
Ответ 3
Это работа для reindex_like
. Начните с оригинала:
df1 = pd.DataFrame([[11, 12], [21, 22]], columns=['c1', 'c2'], index=['i1', 'i2'])
Создайте пустой DataFrame и переиндексируйте его как df1:
pd.DataFrame().reindex_like(df1)
Out:
c1 c2
i1 NaN NaN
i2 NaN NaN
Ответ 4
Вы можете просто mask
на notna()
i.e
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
Ответ 5
Простая альтернатива - сначала скопируйте базовую структуру или индексы и столбцы с типом данных из исходного фрейма данных (df1) в df2
df2 = df1.iloc[0:0]
Затем заполните ваш фреймворк пустыми строками - псевдокодом, который нужно будет адаптировать, чтобы лучше соответствовать вашей фактической структуре:
s = pd.Series([Nan,Nan,Nan], index=['Col1', 'Col2', 'Col3'])
цикл через строки в df1
df2 = df2.append(s)