我需要导入一个有 300+ 列的 csv 文件,在这些列中,只有第一列需要指定为类别,而其余列应该为 float 32 或更少。我猜我可以通过列索引指定列的数据类型。我的问题是:基于列索引指定数据类型的最佳方法是什么?
Col_A Col_B Col_C Col_D
001 1 2 1.2
002 2 3 3.5
003 3 4.5 7
004 4 6.5 10
我尝试的代码是:
df = pd.read_csv(path, low_memory=False,
dtype={'Col_A': 'category', [2:]: np.float32)}
有两种情况:
- 您知道并因此可以提前为每列指定最佳类型;或
- 您事先不知道最佳类型,必须在读取文件后转换为最佳类型。
提前指定
这是直截了当的情况。使用字典:
type_dict = {'Col_A': 'category', 'Col_B': 'int16',
'Col_C': 'float16', 'Col_D': 'float32'}
df = pd.read_csv(myfile, delim_whitespace=True, dtype=type_dict)
如果您事先不知道列名称,只需在第一步中阅读列:
cols = pd.read_csv(myfile, delim_whitespace=True, nrows=0).columns
# Index(['Col_A', 'Col_B', 'Col_C', 'Col_D'], dtype='object')
type_dict = {'Col_A': 'category', **{col: 'float32' for col in cols[1:]}}
df = pd.read_csv(myfile, delim_whitespace=True, dtype=type_dict)
阅读后指定
通常,您事先不会知道最佳类型。在这种情况下,您可以正常读取数据,并在后续步骤中显式执行int
和float
转换:
df = pd.read_csv(myfile, delim_whitespace=True, dtype={'Col_A': 'category'})
cols = {k: df.select_dtypes([k]).columns for k in ('integer', 'float')}
for col_type, col_names in cols.items():
df[col_names] = df[col_names].apply(pd.to_numeric, downcast=col_type)
print(df.dtypes)
Col_A category
Col_B int8
Col_C float32
Col_D float32
dtype: object
用于测试的设置
from io import StringIO
myfile = StringIO("""Col_A Col_B Col_C Col_D
001 1 2 1.2
002 2 3 3.5
003 3 4.5 7
004 4 6.5 10""")
我认为以下内容将达到目的:
df = pd.read_csv(path, low_memory=False, dtype={'Col_A':'category'})
或者,如果您知道它将是第一列:
df = pd.read_csv(path, low_memory=False, dtype={0:'category'})
读取两次,第一次获取所有列,第二次,读取时指定dtype。
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD'))
df.to_csv('tmp.csv',index=False)
path = 'tmp.csv'
df =pd.read_csv(path)
type_dict = {}
for key in df.columns:
if key == 'A':
type_dict[key]='category'
else:
type_dict[key]=np.float32
df = pd.read_csv(path,dtype=type_dict)
print(df.dtypes)