Python Pandas,创建空的DataFrame并指定列数据类型

17

我发现自己经常需要做一件事,在Pandas中实现这个功能非常困难。假设我需要创建一个指定索引类型和名称以及列类型和名称的空的DataFrame。(例如,我可能想在稍后填充它,比如在循环中)。我发现最简单的方法是为每个列创建一个空的pandas.Series对象,指定其dtype,将它们放入一个字典中,并将该字典传递到DataFrame构造函数中。具体步骤如下:

def create_empty_dataframe():
    index = pandas.Index([], name="id", dtype=int)
    column_names = ["name", "score", "height", "weight"]
    series = [pandas.Series(dtype=str), pandas.Series(dtype=int), pandas.Series(dtype=float), pandas.Series(dtype=float)]
    columns = dict(zip(column_names, series))
    return pandas.DataFrame(columns, index=index, columns=column_names)
    # The columns=column_names is required because the dictionary will in general put the columns in arbitrary order.

第一个问题:上面的方法真的是最简单的方法吗?这样做有很多复杂的地方。我真正想做的,也相信很多人真正想做的,是像下面这样做。

df = pandas.DataFrame(columns=["id", "name", "score", "height", "weight"], dtypes=[int, str, int, float, float], index_column="id") 

第二个问题。 Pandas中是否可能使用这种语法?如果不行,开发人员是否考虑支持类似的语法?对我来说,它真的应该像上面的语法一样简单。

5个回答

11

不幸的是,DateFrame 构造函数只接受一个 dtype 描述符,但您可以通过使用 read_csv 稍作一些小手段:

In [143]:
import pandas as pd
import io
cols=["id", "name", "score", "height", "weight"]
df = pd.read_csv(io.StringIO(""), names=cols, dtype=dict(zip(cols,[int, str, int, float, float])), index_col=['id']) 
df.info()

<class 'pandas.core.frame.DataFrame'>
Int64Index: 0 entries
Data columns (total 4 columns):
name      0 non-null object
score     0 non-null int32
height    0 non-null float64
weight    0 non-null float64
dtypes: float64(2), int32(1), object(1)
memory usage: 0.0+ bytes

因此,您可以看到dtypes符合要求,并且索引设置为所需内容:

In [145]:

df.index
Out[145]:
Int64Index([], dtype='int64', name='id')

好的作弊!那么你是说,如果不作弊,我的复杂方法确实是最简单的方法吗? - Ray
我认为使用read_csv是最简单的方法,与标准的DataFrame构造函数相比具有更高的灵活性,除了你有意读取一个空文件之外,这并不算作弊。 - EdChum
不确定为什么您压缩了列和类型。为了清晰起见,我会将其保留为字典。 - Steve Scott

7
您可以通过使用字典来简化操作:
def create_empty_dataframe():
    index = pandas.Index([], name="id", dtype=int)
    # specify column name and data type 
    columns = [('name', str),
               ('score', int),
               ('height', float),
               ('weight', float)]
    # create the dataframe from a dict
    return pandas.DataFrame({k: pandas.Series(dtype=t) for k, t in columns})

这样做可以更轻松地创建一个任意的数据框,而无需在代码中修改多个位置。

这个解决方案非常有效,并且阅读起来更加容易。 - undefined
我用了这个方法,只是做了一个非常小的修改,即用字典来定义列的数据类型,而不是用元组的列表,并相应地修改了字典推导式。 - undefined

1
你可以通过替换的方式设置DataFrame列的数据类型:
df['column_name'] = df['column_name'].astype(float)

1
import pandas as pd
df = pd.DataFrame([{'col00':int(0),'col01':float(0),'col02':str('xx')}])
df = pd.DataFrame([], None, df.columns)
print df

我完成了第一个任务,然后使用 df.types 查看数据类型,结果显示为 int64float64object。但是在完成第二个任务后,df.types 报告每列的类型都是 object,因此我认为数据类型没有被保留。 - bartonstanley

0
这是一个基于 @Elliot 的答案的通用函数:
import pandas as pd


def create_empty_DataFrame(columns, index_col):
    index_type = next((t for name, t in columns if name == index_col))
    df = pd.DataFrame({name: pd.Series(dtype=t) for name, t in columns if name != index_col},
                      index=pd.Index([], dtype=index_type))
    cols = [name for name, _ in columns]
    cols.remove(index_col)
    return df[cols]

请注意,必须使用return df[cols]而不是return df来保留非索引列的顺序。以下是一些测试代码:
columns = [
    ('id', str),
    ('primary', bool),
    ('side', str),
    ('quantity', int),
    ('price', float)]

table = create_empty_DataFrame(columns, 'id')

检查 dtypes 和索引:

table.info()

<class 'pandas.core.frame.DataFrame'>
Index: 0 entries
Data columns (total 4 columns):
primary     0 non-null bool
side        0 non-null object
quantity    0 non-null int64
price       0 non-null float64
dtypes: bool(1), float64(1), int64(1), object(1)
memory usage: 0.0+ bytes

table.index

Index([], dtype='object', name='id')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接