在Pandas中创建指定列类型的空数据框


74

我试图用索引创建一个空的数据框并指定列类型。我这样做的方式如下:

df = pd.DataFrame(index=['pbp'],columns=['contract',
                                         'state_and_county_code',
                                         'state',
                                         'county',
                                         'starting_membership',
                                         'starting_raw_raf',
                                         'enrollment_trend',
                                         'projected_membership',
                                         'projected_raf'],
                                dtype=['str', 'str', 'str', 'str', 'int', 'float', 'float', 'int', 'float'])

但是,出现以下错误,

TypeError: data type not understood

这是什么意思?


我认为您不能以这种方式指定dtypes,您可以传递单个类型,例如str但不是字符串列表。分配列值时将推断dtype。我认为完全
不必

2
@EdChum根据文档是正确的,我想知道为什么为什么构造函数不允许这样做……从一开始就为了分配目的而创建具有类型的空数据框会不会更有效?
jimijazz

Answers:


28

您可以使用以下内容:

df = pd.DataFrame({'a': pd.Series([], dtype='int'),
                   'b': pd.Series([], dtype='str'),
                   'c': pd.Series([], dtype='float')})

然后,如果您致电df

>>> df 
Empty DataFrame 
Columns: [a, b, c]
Index: []

如果您检查其类型

>>> df.dtypes
a      int32
b     object
c    float64
dtype: object

这个答案也适用于非空数据帧,这正是我所寻找的:df = pd.DataFrame({'x': [1, 2, 4], 'y': pd.Series(['odd', 'even', 'even'], dtype='category')})
ruancomelli

Kinda可以输入很多内容,但确实可以满足我的意思。谢谢!
Artur

25

你可以这样

import numpy
import pandas

dtypes = numpy.dtype([
          ('a', str),
          ('b', int),
          ('c', float),
          ('d', numpy.datetime64),
          ])
data = numpy.empty(0, dtype=dtypes)
df = pandas.DataFrame(data)

23

这真的闻起来像个虫子。

这是另一个(简单的)解决方案。

import pandas as pd
import numpy as np

def df_empty(columns, dtypes, index=None):
    assert len(columns)==len(dtypes)
    df = pd.DataFrame(index=index)
    for c,d in zip(columns, dtypes):
        df[c] = pd.Series(dtype=d)
    return df

df = df_empty(['a', 'b'], dtypes=[np.int64, np.int64])
print(list(df.dtypes)) # int64, int64

14

这是一个老问题,但是我没有一个可靠的答案(尽管@eric_g非常接近)。

您只需要创建一个包含key:value对字典的空数据框。键是您的列名,值是一个空数据类型。

因此,在示例数据集中,其外观如下(熊猫0.25和python 3.7):

variables = {'contract':'',
             'state_and_county_code':'',
             'state':'',
             'county':'',
             'starting_membership':int(),
             'starting_raw_raf':float(),
             'enrollment_trend':float(),
             'projected_membership':int(),
             'projected_raf':float()}

df = pd.DataFrame(variables, index=[])

在旧的熊猫版本中,可能需要执行以下操作:

df = pd.DataFrame(columns=[variables])

1
我不认为这是可行的,因为Pandas抛出一个错误说dict is unhashable type(这是可以理解的)。并且,在文档中没有提及这种格式。
安纳托利·谢尔巴科夫

我正在代码中积极使用它,效果很好。我使用的是熊猫0.22.0,你呢?
SummerEla

我也遇到与@An​​atolyScherbakov相同的问题。我正在使用0.23.0。如果可行,这似乎是最直接的方法。
teemoleen

1
我已经更新了上面的代码,以与最新版本的python和pandas一起使用。希望能帮助到你。
SummerEla

11

只是一句话。

您可以使用np.dtype以下方法解决类型错误:

pd.DataFrame(index = ['pbp'], columns = ['a','b'], dtype = np.dtype([('str','float')]))

但是您却得到了:

NotImplementedError: compound dtypes are not implementedin the DataFrame constructor

1
这确实是正确的答案。即使修复了TypeError,大熊猫也不愿去实现。您甚至无法从现有的compound-dtype DataFrame复制dtype来启动一个新的空DataFrame,这似乎是一个有效的用例。
Mike Jarvis

1
@MikeJarvis如果要复制现有框架的dtype,则可以从该框架中选择0行,并使空DF具有相同的dtype。例如cpy = df.loc[[False]*len(df)]应该做的把戏
科里

2
我不知道如果它不起作用,那么成为“正确答案”意味着什么。我认为您说的是这样的话:“我希望这能奏效”。
凯尔·佩纳

5

遇到相同的问题后,我发现了这个问题。我更喜欢以下解决方案(Python 3)用于创建没有索引的空DataFrame 。

import numpy as np
import pandas as pd

def make_empty_typed_df(dtype):
    tdict = np.typeDict
    types = tuple(tdict.get(t, t) for (_, t, *__) in dtype)
    if any(t == np.void for t in types):
        raise NotImplementedError('Not Implemented for columns of type "void"')
    return pd.DataFrame.from_records(np.array([tuple(t() for t in types)], dtype=dtype)).iloc[:0, :]

测试出来...

from itertools import chain

dtype = [('col%d' % i, t) for i, t in enumerate(chain(np.typeDict, set(np.typeDict.values())))]
dtype = [(c, t) for (c, t) in dtype if (np.typeDict.get(t, t) != np.void) and not isinstance(t, int)]

print(make_empty_typed_df(dtype))

出:

Empty DataFrame

Columns: [col0, col6, col16, col23, col24, col25, col26, col27, col29, col30, col31, col32, col33, col34, col35, col36, col37, col38, col39, col40, col41, col42, col43, col44, col45, col46, col47, col48, col49, col50, col51, col52, col53, col54, col55, col56, col57, col58, col60, col61, col62, col63, col64, col65, col66, col67, col68, col69, col70, col71, col72, col73, col74, col75, col76, col77, col78, col79, col80, col81, col82, col83, col84, col85, col86, col87, col88, col89, col90, col91, col92, col93, col95, col96, col97, col98, col99, col100, col101, col102, col103, col104, col105, col106, col107, col108, col109, col110, col111, col112, col113, col114, col115, col117, col119, col120, col121, col122, col123, col124, ...]
Index: []

[0 rows x 146 columns]

以及数据类型...

print(make_empty_typed_df(dtype).dtypes)

出:

col0      timedelta64[ns]
col6               uint16
col16              uint64
col23                int8
col24     timedelta64[ns]
col25                bool
col26           complex64
col27               int64
col29             float64
col30                int8
col31             float16
col32              uint64
col33               uint8
col34              object
col35          complex128
col36               int64
col37               int16
col38               int32
col39               int32
col40             float16
col41              object
col42              uint64
col43              object
col44               int16
col45              object
col46               int64
col47               int16
col48              uint32
col49              object
col50              uint64
               ...       
col144              int32
col145               bool
col146            float64
col147     datetime64[ns]
col148             object
col149             object
col150         complex128
col151    timedelta64[ns]
col152              int32
col153              uint8
col154            float64
col156              int64
col157             uint32
col158             object
col159               int8
col160              int32
col161             uint64
col162              int16
col163             uint32
col164             object
col165     datetime64[ns]
col166            float32
col167               bool
col168            float64
col169         complex128
col170            float16
col171             object
col172             uint16
col173          complex64
col174         complex128
dtype: object

添加索引会很棘手,因为大多数数据类型都没有真正的缺失值,因此最终将它们转换为具有本机缺失值的其他类型(例如,将ints强制转换为floats或objects),但是如果您已经完成了指定类型的数据,那么您随时可以根据需要插入行,并且将尊重您的类型。这可以通过以下方式完成:

df.loc[index, :] = new_row

再次,正如@Hun指出的,这不是熊猫如何被使用的方式。


3

我的解决方案(不设置索引)是使用列名初始化数据框并使用astype()方法指定数据类型。

df = pd.DataFrame(columns=['contract',
                     'state_and_county_code',
                     'state',
                     'county',
                     'starting_membership',
                     'starting_raw_raf',
                     'enrollment_trend',
                     'projected_membership',
                     'projected_raf'])
df = df.astype( dtype={'contract' : str, 
                 'state_and_county_code': str,
                 'state': str,
                 'county': str,
                 'starting_membership': int,
                 'starting_raw_raf': float,
                 'enrollment_trend': float,
                 'projected_membership': int,
                 'projected_raf': float})

2
我来到了相同的解决方案。您可以使用字典为数据帧定义架构:schema = { 'name': str, 'number': float, 'date': np.datetime64} df = pd.DataFrame(columns=schema.keys()).astype(schema)
Simon Ejsing

@SimonEjsing您的解决方案是一个更优雅的解决方案,感谢您的分享
Korhan '20

2

熊猫不提供纯整数列。您可以使用float列,然后根据需要将该列转换为整数,也可以将其视为对象。您要实现的不是熊猫应该被使用的方式。但是,如果您真的很想要这样做,则可以通过执行此操作来解决TypeError消息。

df1 =  pd.DataFrame(index=['pbp'], columns=['str1','str2','str2'], dtype=str)
df2 =  pd.DataFrame(index=['pbp'], columns=['int1','int2'], dtype=int)
df3 =  pd.DataFrame(index=['pbp'], columns=['flt1','flt2'], dtype=float)
df = pd.concat([df1, df2, df3], axis=1)

    str1 str2 str2 int1 int2  flt1  flt2
pbp  NaN  NaN  NaN  NaN  NaN   NaN   NaN

您可以根据需要重新排列col顺序。但是,这又不是熊猫应该被使用的方式。

 df.dtypes
str1     object
str2     object
str2     object
int1     object
int2     object
flt1    float64
flt2    float64
dtype: object

请注意,将int视为对象。


3
你到底在说什么 当然,Pandas支持整数列。
user2357112支持Monica's

1
dtype=int但是,没有数据传递似乎确实存在问题。
user2357112支持Monica

这绝对看起来像个错误-仍然是最新版本中的行为。你提交了吗?
user48956 '18

它的预期行为,在警告中列出。它是由于那里是没有nanint。您可以在文档中
Victor Uriarte

1
@VictorUriarte不能解释为什么不能在构造函数中指定int列。如果您请求一个int列,然后再插入一个nan,则正确的行为将是促使该列浮动或引发异常
user48956

2

您可以通过将字典传递到DataFrame构造函数中来实现:

df = pd.DataFrame(index=['pbp'],
                  data={'contract' : np.full(1, "", dtype=str),
                        'starting_membership' : np.full(1, np.nan, dtype=float),
                        'projected_membership' : np.full(1, np.nan, dtype=int)
                       }
                 )

这将正确地为您提供如下数据框:

     contract  projected_membership   starting_membership
pbp     ""             NaN           -9223372036854775808

使用dtypes:

contract                 object
projected_membership    float64
starting_membership       int64

也就是说,有两件事要注意:

1)str实际上不是DataFrame列可以处理的类型;取而代之的是回到一般情况object。它仍然可以正常工作。

2)为什么看NaN不到starting_membership?好吧,NaN只为浮点数定义;整数没有“ None”值,因此将其转换np.NaN为整数。如果要使用其他默认值,则可以在np.full呼叫中进行更改。


2
当您可以使用空数组时,无需在列中放置一堆虚拟数据。
user2357112支持Monica's

2

我发现对我来说,最简单的解决方法是为每个单独的列串联一个空序列列表:

import pandas as pd

columns = ['contract',
           'state_and_county_code',
           'state',
           'county',
           'starting_membership',
           'starting_raw_raf',
           'enrollment_trend',
           'projected_membership',
           'projected_raf']
dtype = ['str', 'str', 'str', 'str', 'int', 'float', 'float', 'int', 'float']
df = pd.concat([pd.Series(name=col, dtype=dt) for col, dt in zip(columns, dtype)], axis=1)
df.info()
# <class 'pandas.core.frame.DataFrame'>
# Index: 0 entries
# Data columns (total 9 columns):
# contract                 0 non-null object
# state_and_county_code    0 non-null object
# state                    0 non-null object
# county                   0 non-null object
# starting_membership      0 non-null int32
# starting_raw_raf         0 non-null float64
# enrollment_trend         0 non-null float64
# projected_membership     0 non-null int32
# projected_raf            0 non-null float64
# dtypes: float64(3), int32(2), object(4)
# memory usage: 0.0+ bytes

1

从您的示例中获取列表列和dtype,您可以执行以下操作:

cdt={i[0]: i[1] for i in zip(columns, dtype)}    # make column type dict
pdf=pd.DataFrame(columns=list(cdt))    # create empty dataframe
pdf=pdf.astype(cdt)                    # set desired column types

DataFrame文档说构造函数调用中仅允许单个dtype。


0

在Pandas中创建指定列类型的空数据框

我认为这是完美的!

import pandas as pd

c1 = pd.Series(data=None, dtype='string', name='c1')
c2 = pd.Series(data=None, dtype='bool', name='c2')
c3 = pd.Series(data=None, dtype='float', name='c3')
c4 = pd.Series(data=None, dtype='int', name='c4')

df = pd.concat([c1, c2, c3, c4], axis=1)

df.info('verbose')

我们将列创建为Series并为其指定正确的dtype,然后将Series合并为一个DataFrame,仅此而已

我们有带有dtypes的DataFrame构造函数!

<class 'pandas.core.frame.DataFrame'>
Index: 0 entries
Data columns (total 4 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   c1      0 non-null      string 
 1   c2      0 non-null      bool   
 2   c3      0 non-null      float64
 3   c4      0 non-null      int32  
dtypes: bool(1), float64(1), int32(1), string(1)
memory usage: 0.0+ bytes
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.