有没有办法只复制Pandas DataFrame的结构(而不​​是数据)?

时间:2014-12-14 08:49:36

标签: python 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

是否有更惯用的方法呢?

9 个答案:

答案 0 :(得分:26)

version 0.18 of pandas, the DataFrame constructor中没有选项来创建数据框,就像使用NaN而不是值来创建另一个数据框一样。

您使用的代码df2 = pd.DataFrame(columns=df1.columns, index=df1.index)是最合乎逻辑的方式,改进它的唯一方法是拼出更多您正在做的是添加data=None,以便其他编码人员直接看到你有意遗漏了你正在创建的新数据框中的数据。

TLDR:我的建议是:

显式优于隐式

df2 = pd.DataFrame(data=None, columns=df1.columns, index=df1.index)

非常像你的,但更多的拼写。

答案 1 :(得分:22)

这是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   

答案 2 :(得分:10)

让我们从一些样本数据开始

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

答案 3 :(得分:6)

一个简单的替代方法 - 首先将原始数据框(df1)中数据类型的基本结构或索引和列复制到df2

df2 = df1.iloc[0:0]

然后用空行填充数据帧 - 需要调整伪代码以更好地匹配您的实际结构:

s = pd.Series([Nan,Nan,Nan], index=['Col1', 'Col2', 'Col3'])

遍历df1

中的行
df2 = df2.append(s)

答案 4 :(得分:5)

不是完全回答这个问题,但是对于通过搜索引擎来到这里的人们来说,是一个类似的问题

我的案例是创建数据框架的副本,该副本没有数据也没有索引。通过执行以下操作可以实现这一目标。这将保持列的dtype。

empty_copy = df.drop(df.index)

答案 5 :(得分:2)

你只需mask notna()

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

答案 6 :(得分:0)

这在熊猫0.22中对我有用: df2 = pd.DataFrame(index=df.index.delete(slice(None)), columns=df.columns)

转换类型: df2 = df2.astype(df.dtypes)

delete(slice(None)) 如果您不想保留索引的值。

答案 7 :(得分:0)

我知道这是一个老问题,但我想我会加两分钱。

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

此方法围绕输入数据帧df.dtypes的{​​{1}}属性,dfpd.Series由空pd.DataFrame对象的字典构成,这些对象使用输入列名命名,列顺序取自输入pd.Series

答案 8 :(得分:0)

将 df 结构复制到 df2 的简单方法是:

df2 = pd.DataFrame(columns=df.columns)