2014-01-17 153 views
59

我想设置dtype的多重列在pd.Dataframe(我有我不得不手动解析成列表的列表中的文件,因为文件是不适合用于pd.read_csv分配大熊猫据帧列dtypes

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 

有没有更好的方法?

+0

这可能是一个很好的[bug /功能请求](https://github.com/pydata/pandas/issues/new),目前我不确定dtype arg在做什么(你可以 –

+1

FYI:'df = pd.DataFrame([['a','1'],['b','2']],dtype ='int' ,列= ['x','y'])'“起作用”......但:s –

+1

是的,“起作用”的确如此;不可预知的... – hatmatrix

回答

34

您可以使用convert_objects推断更好dtypes:

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

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

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

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

魔术!

+2

像'type.convert' in R一点点;不错,但是在某些情况下会保留一个明确的规格。 – hatmatrix

+0

@crippledlambda同意,我认为这将是一个很好的功能要求,而不是太难实现。 –

+1

如果您有一列需要是一个字符串,但至少包含一个可以转换为int的值,那么请小心。它所需要的只是一个值,整个字段被转换为float64 –

50

对于那些从谷歌(等)来像我这样的:

convert_objects已被弃用 - 如果你使用它,你会得到这样一个警告:

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

你应该这样做像下面这样:

8

另一种方式来设置的列类型是首先构造一个numpy的记录阵列以所需的类型,填好,然后将它传递给数据帧构造器。

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 
0

面临类似的问题给你。在我的情况下,我有1000个来自cisco日志的文件,我需要手动解析。

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

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

最终我将这些数据帧连接到一个大型数据框中,并将其转储到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 

不是很Python的....但做这项工作

希望它能帮助。

JC

15

你可以明确地与大熊猫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 
0

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

# 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, 
    } 
)