分配 pandas 数据框列 dtypes

Posted

技术标签:

【中文标题】分配 pandas 数据框列 dtypes【英文标题】:Assign pandas dataframe column dtypes 【发布时间】:2014-02-07 11:37:35 【问题描述】:

我想在pd.Dataframe 中设置多个列的dtypes(我有一个文件,我必须手动解析为列表列表,因为该文件不适用于pd.read_csv

import pandas as pd
print pd.DataFrame([['a','1'],['b','2']],
                   dtype='x':'object','y':'int',
                   columns=['x','y'])

我明白了

ValueError: entry not a 2- or 3- tuple

我可以设置它们的唯一方法是循环遍历每个列变量并使用astype 重铸。

dtypes = 'x':'object','y':'int'
mydata = pd.DataFrame([['a','1'],['b','2']],
                      columns=['x','y'])
for c in mydata.columns:
    mydata[c] = mydata[c].astype(dtypes[c])
print mydata['y'].dtype   #=> int64

有没有更好的办法?

【问题讨论】:

这可能是一个很好的bug / feature request,目前我不确定 dtype arg 在做什么(你可以传递一个标量,但它并不严格)... 仅供参考:df = pd.DataFrame([['a','1'],['b','2']], dtype='int', columns=['x','y'])“有效”...但是:s 是的,确实“有效”;出乎意料... 这个 GitHub 问题可能很快就会变得相关:github.com/pydata/pandas/issues/9287 【参考方案1】:

从 0.17 开始,您必须使用显式转换:

pd.to_datetime, pd.to_timedelta and pd.to_numeric

(如下所述,不再有“魔法”,convert_objects 已在 0.17 中弃用)

df = pd.DataFrame('x': 0: 'a', 1: 'b', 'y': 0: '1', 1: '2', 'z': 0: '2018-05-01', 1: '2018-05-02')

df.dtypes

x    object
y    object
z    object
dtype: object

df

   x  y           z
0  a  1  2018-05-01
1  b  2  2018-05-02

您可以将这些应用于要转换的每一列:

df["y"] = pd.to_numeric(df["y"])
df["z"] = pd.to_datetime(df["z"])    
df

   x  y          z
0  a  1 2018-05-01
1  b  2 2018-05-02

df.dtypes

x            object
y             int64
z    datetime64[ns]
dtype: object

并确认 dtype 已更新。


熊猫 0.12 - 0.16 的旧/弃用答案:您可以使用 convert_objects 推断更好的 dtypes:

In [21]: df
Out[21]: 
   x  y
0  a  1
1  b  2

In [22]: df.dtypes
Out[22]: 
x    object
y    object
dtype: object

In [23]: df.convert_objects(convert_numeric=True)
Out[23]: 
   x  y
0  a  1
1  b  2

In [24]: df.convert_objects(convert_numeric=True).dtypes
Out[24]: 
x    object
y     int64
dtype: object

魔法!(很遗憾看到它被弃用了。)

【讨论】:

有点像R中的type.convert;不错,但在某些情况下确实让人希望明确说明。 如果有一列需要是字符串但至少包含一个可以转换为 int 的值,请小心。只需要一个值,整个字段都转换为 float64 我注意到 convert_objects() 已被弃用...我不确定是什么取代了它? 要重新推断对象列的数据类型,请使用 DataFrame.infer_objects() @smci 好的,我已经编辑过了。有一堆已弃用的答案,我需要想办法找到所有答案。【参考方案2】:

对于那些来自谷歌(等)的人,比如我自己:

convert_objects 自 0.17 起已被弃用 - 如果您使用它,您会收到如下警告:

FutureWarning: convert_objects is deprecated.  Use the data-type specific converters 
pd.to_datetime, pd.to_timedelta and pd.to_numeric.

您应该执行以下操作:

df =df.astype(np.float) df["A"] =pd.to_numeric(df["A"])

【讨论】:

如果你提供了一些pd.to_datetime, to_timedelta, to_numeric 的例子,这应该是公认的答案。【参考方案3】:

您可以使用 pandas DataFrame.astype(dtype, copy=True, raise_on_error=True, **kwargs) 显式设置类型,并使用您想要的 dtypes 传入字典 dtype

这是一个例子:

import pandas as pd
wheel_number = 5
car_name = 'jeep'
minutes_spent = 4.5

# set the columns
data_columns = ['wheel_number', 'car_name', 'minutes_spent']

# create an empty dataframe
data_df = pd.DataFrame(columns = data_columns)
df_temp = pd.DataFrame([[wheel_number, car_name, minutes_spent]],columns = data_columns)
data_df = data_df.append(df_temp, ignore_index=True) 

你得到

In [11]: data_df.dtypes
Out[11]:
wheel_number     float64
car_name          object
minutes_spent    float64
dtype: object

data_df = data_df.astype(dtype= "wheel_number":"int64",
        "car_name":"object","minutes_spent":"float64")

现在你可以看到它已经改变了

In [18]: data_df.dtypes
Out[18]:
wheel_number       int64
car_name          object
minutes_spent    float64

【讨论】:

【参考方案4】:

另一种设置列类型的方法是先用你想要的类型构造一个 numpy 记录数组,填充它,然后将它传递给 DataFrame 构造函数。

import pandas as pd
import numpy as np    

x = np.empty((10,), dtype=[('x', np.uint8), ('y', np.float64)])
df = pd.DataFrame(x)

df.dtypes ->

x      uint8
y    float64

【讨论】:

【参考方案5】:

最好使用类型化的 np.arrays,然后将数据和列名作为字典传递。

import numpy as np
import pandas as pd
# Feature: np arrays are 1: efficient, 2: can be pre-sized
x = np.array(['a', 'b'], dtype=object)
y = np.array([ 1 ,  2 ], dtype=np.int32)
df = pd.DataFrame(
   'x' : x,    # Feature: column name is near data array
   'y' : y,
   
 )

【讨论】:

这是迄今为止最好的答案!我希望它能快速上升。【参考方案6】:

面临与您类似的问题。就我而言,我有 1000 个来自 cisco 日志的文件需要手动解析。

为了灵活处理字段和类型,我已经使用 StringIO + read_cvs 成功进行了测试,它确实接受了 dtype 规范的字典。

我通常将每个文件(5k-20k 行)放入缓冲区并动态创建 dtype 字典。

最终我将这些数据帧连接(使用分类......感谢 0.19)成一个大数据帧,然后转储到 hdf5 中。

类似的东西

import pandas as pd
import io 

output = io.StringIO()
output.write('A,1,20,31\n')
output.write('B,2,21,32\n')
output.write('C,3,22,33\n')
output.write('D,4,23,34\n')

output.seek(0)


df=pd.read_csv(output, header=None,
        names=["A","B","C","D"],
        dtype="A":"category","B":"float32","C":"int32","D":"float64",
        sep=","
       )

df.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 4 columns):
A    5 non-null category
B    5 non-null float32
C    5 non-null int32
D    5 non-null float64
dtypes: category(1), float32(1), float64(1), int32(1)
memory usage: 205.0 bytes
None

不是很pythonic....但可以完成工作

希望对你有帮助。

JC

【讨论】:

以上是关于分配 pandas 数据框列 dtypes的主要内容,如果未能解决你的问题,请参考以下文章

处理具有混合日期格式的 Pandas 数据框列

以字符串形式存储在 Pandas 数据框列中的解析列表

将所有数据框列转换为浮动的最快方法 - pandas astype 慢

分别绘制所有 pandas 数据框列

根据列名删除 Pandas 数据框列

来自 pandas 数据框列的 dict