pandas数据类型

pandas数据类型

大多数情况下,pandas在Series和DataFrame的columns中使用numpy 的 arrays 和 dtypes 。
numpy提供对float,int,bool,timedelta64[ns],datetime64[ns]数据类型的支持。
但是numpy不支持timezone-aware datetimes

pandas和一些第三方库在一些地方扩展了numpy的类型系统。

pandas扩展了以下数据类型:

Kind of DataData TypeScalarArrayDocumentation
tz-aware datetimeDatetimeTZDtypeTimestamparrays.DatetimeArrayTime zone handling
CategoricalCategoricalDtype(none)CategoricalCategorical data
period (time spans)PeriodDtypePeriodarrays.PeriodArrayTime span representation
sparseSparseDtype(none)arrays.SparseArraySparse data structures
intervalsIntervalDtypeIntervalarrays.IntervalArrayIntervalIndex
nullable integerInt64Dtype, …(none)arrays.IntegerArrayNullable integer data type

panda使用对象dtype存储字符串。

最后,可以使用对象dtype存储任意对象,但应尽可能避免使用(有关性能以及与其他库和方法的互操作性)。

DataFrame的一个方便的dtypes属性,设置Series column的属性。

import numpy as np
import pandas as pd
dft = pd.DataFrame({
    'A':np.random.rand(3),
    'B':1,
    'C':'foo',
    'D':pd.Timestamp('20010102'),
    'E':pd.Series([1.]*3).astype('float32'),
    'F':False,
    'G':pd.Series([1]*3,dtype='int8')
})
dft
ABCDEFG
00.1023921foo2001-01-021.0False1
10.5977351foo2001-01-021.0False1
20.5206561foo2001-01-021.0False1
dft.dtypes
A           float64
B             int64
C            object
D    datetime64[ns]
E           float32
F              bool
G              int8
dtype: object
dft.A.dtype
dtype('float64')

如果pandas对象在单个列中包含具有多个dtypes的数据,则将选择一个能容纳所有数据类型的dtype作为该列的dtype(object是最通用的)。

pd.Series([1,2,3,4,5,6.])
0    1.0
1    2.0
2    3.0
3    4.0
4    5.0
5    6.0
dtype: float64
pd.Series([1,2,3,6.,'foo'])
0      1
1      2
2      3
3      6
4    foo
dtype: object

可以通过调用以下内容找到DataFrame中每种类型的列数.DataFrame.dtypes.value_counts().

dft.dtypes.value_counts()
datetime64[ns]    1
float32           1
bool              1
object            1
int64             1
int8              1
float64           1
dtype: int64

数值类型将会传播并共存于DataFrame中。如果一个dtype被传入(不管是通过dtype关键字,传入的ndarray还是Series),她会被保存在DataFrame中。而且不同类型的numeric dtypes 不会被组合在一起。

以下是一个示例:

df1 = pd.DataFrame(np.random.rand(8,1),columns=['A'],dtype='float32')
df1
A
00.889056
10.108117
20.494659
30.308186
40.217554
50.485128
60.344791
70.161693
df1.dtypes
A    float32
dtype: object
df2 = pd.DataFrame({
    'A':pd.Series(np.random.randn(8),dtype='float16'),
    'B':pd.Series(np.random.rand(8)),
    'C':pd.Series(np.array(np.random.randn(8),dtype='uint8'))
})
df2
ABC
0-1.4277340.1584450
1-0.2917480.3151840
2-0.7558590.395976255
3-1.8994140.1152101
4-0.5654300.9627110
5-1.7685550.0042230
6-1.6201170.176138255
7-0.8051760.5949550
df2.dtypes
A    float16
B    float64
C      uint8
dtype: object

默认值

默认情况下,int值保存为int64float值保存为float64

pandas不会根据操作系统来选择使用int64还是int32,但是numpy在创建arrays的时候,会根据操作系统选择使用int32还是int64。

向上转型

与其他类型结合使用时,可能会转换类型,这意味着它们会从当前类型向上转型(例如,从int转换为float)。

df3 = df1.reindex_like(df2).fillna(value=0.0) + df2
df3
ABC
0-0.5386780.1584450.0
1-0.1836310.3151840.0
2-0.2612000.395976255.0
3-1.5912280.1152101.0
4-0.3478760.9627110.0
5-1.2834270.0042230.0
6-1.2753270.176138255.0
7-0.6434830.5949550.0
df3.dtypes
A    float32
B    float64
C    float64
dtype: object

DataFrame.to_numpy()会返回的numpy对象可能会强制数量类型向上转型。

df3.to_numpy().dtype
dtype('float64')

astype

可以使用astype()方法可以容易的将dtype转变为另一种。它将默认返回一个复制,即使dtype没有改变(传入参数copy=False可以默认行为)。如果astype操作不合法,将抛出异常。

向上转型是根据numpy的规则。如果两个不同的dtype在一次操作中被涉及,那么更通用的那个将会被使用。

df3
ABC
0-0.5386780.1584450.0
1-0.1836310.3151840.0
2-0.2612000.395976255.0
3-1.5912280.1152101.0
4-0.3478760.9627110.0
5-1.2834270.0042230.0
6-1.2753270.176138255.0
7-0.6434830.5949550.0
df3.dtypes
A    float32
B    float64
C    float64
dtype: object
df3.astype('float32').dtypes
A    float32
B    float32
C    float32
dtype: object

将DataFrame中的某些Series转换为一个特殊的类型

dft = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6], 'c': [7, 8, 9]})
dft.dtypes
a    int64
b    int64
c    int64
dtype: object
dft[['a', 'b']] = dft[['a', 'b']].astype(np.uint8)
dft.dtypes
a    uint8
b    uint8
c    int64
dtype: object

当尝试使用astype()和loc()将列的子集转换为指定类型时,会发生向上转换。

下面这段代码会产生意想不到的结果。

dft = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6], 'c': [7, 8, 9]})
dft.loc[:, ['a', 'b']].astype(np.uint8).dtypes
a    uint8
b    uint8
dtype: object
dft.loc[:, ['a', 'b']] = dft.loc[:, ['a', 'b']].astype(np.uint8)
dft.dtypes
a    int64
b    int64
c    int64
dtype: object

object转换

panda提供了各种函数来尝试强制类型从对象dtype转换为其他类型。如果数据已经是正确的类型,但存储在对象数组中,则可以使用datafram .infer_objects()seri_infer_objects()方法来软转换为正确的类型。

import datetime
df =pd.DataFrame([
    [1,2],['a','b'],[datetime.datetime(2016,3,2),datetime.datetime(2016,3,2)]
])
df
01
012
1ab
22016-03-02 00:00:002016-03-02 00:00:00
df = df.T
df.dtypes
0            object
1            object
2    datetime64[ns]
dtype: object

因为数据被转置,原始数据存储的是object,所以上面的df.dtypes输出的是object。

使用infer_object()可以修正dtypes:

df.infer_objects().dtypes
0             int64
1            object
2    datetime64[ns]
dtype: object

以下方法可以将一维对象数组或者标量转化为其他类型

  • to_numeric():转变成numeric dtypes
  • to_datetime() :转变为datetime objects
  • to_timedelta() :转变为timedelta objects
 m = ['5us', pd.Timedelta('1day')]
m
['5us', Timedelta('1 days 00:00:00')]
pd.to_timedelta(m)
TimedeltaIndex(['0 days 00:00:00.000005', '1 days 00:00:00'], dtype='timedelta64[ns]', freq=None)

为了强制转换类型,可以传入一个errors参数,它将用指定怎么处理哪些不能没转化为指定类型的元素。

默认errors=raise,意味着在转化过程中遇到错误都会抛出。如果errors=coerce,错误将会被忽略并且将出错的元素转化为pd.NaT或者pd.NaN类型。

当读取数据,这些数据大部分是符合要求的类型,但是有一些不符合的元素混在其中,希望把不符合的设置为缺失,上面说讲的特性将非常有用。

import datetime
m = ['apple', datetime.datetime(2016, 3, 2)]
pd.to_datetime(m, errors='coerce')
DatetimeIndex(['NaT', '2016-03-02'], dtype='datetime64[ns]', freq=None)
m = ['apple', 2, 3]
pd.to_numeric(m, errors='coerce')
array([nan,  2.,  3.])
m = ['apple', pd.Timedelta('1day')]
pd.to_timedelta(m, errors='coerce')
TimedeltaIndex([NaT, '1 days'], dtype='timedelta64[ns]', freq=None)

除了object转换,to_numeric()还提供了一个downcast参数,它可以将新的数字数据向下转换为更小的dtype,这样可以节省内存:

m = ['1', 2, 3]
pd.to_numeric(m, downcast='integer')  
array([1, 2, 3], dtype=int8)
pd.to_numeric(m, downcast='signed')
array([1, 2, 3], dtype=int8)
pd.to_numeric(m, downcast='unsigned')
array([1, 2, 3], dtype=uint8)
 pd.to_numeric(m, downcast='float')  
array([1., 2., 3.], dtype=float32)

由于这些方法只适用于一维数组、列表或标量;它们不能直接用于多维对象(如DataFrames)。但是,使用apply(),我们可以在每一列上有效地“应用”这个函数:

import datetime
df = pd.DataFrame([
    ['2016-07-09', datetime.datetime(2016, 3, 2)]] * 2, dtype='O')
df
01
02016-07-092016-03-02 00:00:00
12016-07-092016-03-02 00:00:00
df.apply(pd.to_datetime)
01
02016-07-092016-03-02
12016-07-092016-03-02
df = pd.DataFrame([['1.1', 2, 3]] * 2, dtype='O')
df
012
01.123
11.123
df.apply(pd.to_numeric)
012
01.123
11.123
df = pd.DataFrame([['5us', pd.Timedelta('1day')]] * 2, dtype='O')

df
01
05us1 days 00:00:00
15us1 days 00:00:00
df.apply(pd.to_timedelta)
01
000:00:00.0000051 days
100:00:00.0000051 days

陷阱

integer类型执行操作可以很容易的向上转型为float类型。
在不引入nans的情况下,将保留输入数据的dtype。

dfi = df3.astype('int32')
dfi['E'] =1
dfi
ABCE
00001
10001
2002551
3-1011
40001
5-1001
6-102551
70001
dfi.dtypes
A    int32
B    int32
C    int32
E    int64
dtype: object
casted = dfi[dfi > 0]
casted.dtypes
A    float64
B    float64
C    float64
E      int64
dtype: object

可以看到,经过操作后,int32变成了float64, 但是如果数据原本是float32,操作后不会被转换成float64


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值