如何在pandas DataFrame中按列设置数据类型
我想把一些数据导入到一个叫做pandas的表格工具中,并且在导入的时候为每一列指定数据类型。这样做是为了处理一些比较大的数据集,里面有很多不同的列。不过,举个例子来说:
myarray = np.random.randint(0,5,size=(2,2))
mydf = pd.DataFrame(myarray,columns=['a','b'], dtype=[float,int])
mydf.dtypes
结果是:
类型错误:数据类型无法理解
我试过其他几种方法,比如:
mydf = pd.DataFrame(myarray,columns=['a','b'], dtype={'a': int})
类型错误:类型为'type'的对象没有长度
如果我写 dtype=(float,int)
,那么这两列都会被当作浮点数格式处理。
最后,我希望能像传递列名那样,直接传递一个数据类型的列表。
6 个回答
在最近版本的pandas(现在是2.X版本)中,有一个解决方案是可以给DataFrame.astype()
传递一个字典,这个字典的键是列名,值是该列应该是什么类型。
其他评论和回答提到,在以前的版本中这是不可能的,但在2.X版本中至少可以做到这一点。
df = pd.DataFrame(
{'some_ints': [1, 2, 3], 'some_strs': ['a', 'b', 'c']},
dtype={'some_ints': 'str', 'some_strs': 'str'}
)
df.dtypes.to_dict()
>>> {'some_ints': dtype('O'), 'some_strs': dtype('O')}
df = df.astype({'some_ints': 'int64', 'some_strs': 'str'})
df.dtypes.to_dict()
>>> {'some_ints': dtype('int64'), 'some_strs': dtype('O')}
另一个小技巧是,如果你把可能导致类型转换的操作连在一起,可以在df.dtypes.to_dict()
的输出上调用.astype
。
举个例子:
df = (
df
.some_type_changing_method()
.astype(df.dtypes.to_dict()
)
这样可以确保在连锁操作的开始和结束时,你的数据类型是匹配的,或者如果类型无法转换(比如把nans转换成整数),就会报错。
在Pandas 1.5.3版本中,可以明确指定数据类型:
import pandas as pd
data = (['Alex', 10],["Bob",12],["Clarke",11.05])
df = pd.DataFrame(data,columns=("Name", "Age"),dtype=(str, float))
print(df)
你可以试着把一组Series
对象放进DataFrame
的构造函数里,这样你就能更具体地控制创建过程,而且应该能更清楚地理解发生了什么。下面是一个模板版本(data1
可以是一个数组等等):
df = pd.DataFrame({'column1':pd.Series(data1, dtype='type1'),
'column2':pd.Series(data2, dtype='type2')})
这里是一个带数据的例子:
df = pd.DataFrame({'A':pd.Series([1,2,3], dtype='int'),
'B':pd.Series([7,8,9], dtype='float')})
print (df)
A B
0 1 7.0
1 2 8.0
2 3 9.0
print (df.dtypes)
A int32
B float64
dtype: object
我刚遇到这个问题,而pandas的问题还没有解决,所以我想分享一下我的解决方法。假设df
是我的数据框(DataFrame),而dtype
是一个字典,用来把列名和数据类型对应起来:
for k, v in dtype.items():
df[k] = df[k].astype(v)
(注意:在Python 2中使用dtype.iteritems()
)
供参考:
- 允许的数据类型列表(NumPy的
dtypes
):https://docs.scipy.org/doc/numpy-1.12.0/reference/arrays.dtypes.html - Pandas还支持一些其他类型。例如,
category
类型:http://pandas.pydata.org/pandas-docs/stable/categorical.html - 相关的GitHub问题:https://github.com/pandas-dev/pandas/issues/9287
截至pandas的版本0.24.2(目前的稳定版本),你不能直接给DataFrame构造函数传递一个明确的数据类型列表,文档中是这么说明的:
dtype : dtype, default None
Data type to force. Only a single dtype is allowed. If None, infer
不过,dataframe类有一个静态方法,可以让你把一个numpy的结构化数组转换成dataframe,所以你可以这样做:
>>> myarray = np.random.randint(0,5,size=(2,2))
>>> record = np.array(map(tuple,myarray),dtype=[('a',np.float),('b',np.int)])
>>> mydf = pd.DataFrame.from_records(record)
>>> mydf.dtypes
a float64
b int64
dtype: object