Pandas将列转换为不同的dtypes

时间:2014-07-23 14:13:54

标签: python pandas

所以我使用Pandas来创建一个数据框,其中包含一些类型为bool,int64和date time的列。对于较小的数据集,dtypes仍然存在,但对于较大的数据集,pandas会将所有这些转换为对象。谁会知道为什么它这样做以及我如何明确设置类型呢?

阅读CSV:

  twitterDataFrame = pandas.read_csv(DataSetLocation)

  twitterDataFrame['CreatedAt'] = twitterDataFrame['CreatedAt'].map(lambda x: pandas.to_datetime(x,dayfirst=True))
  twitterDataFrame['CreatedAtForCalculations'] = twitterDataFrame['CreatedAt']
  twitterDataFrame['InReplyToStatusID'] = twitterDataFrame['InReplyToStatusID'].map(lambda x: True if pandas.notnull(x) else False)
  twitterDataFrame['InReplyToUserID'] = twitterDataFrame['InReplyToUserID'].map(lambda x: True if pandas.notnull(x) else False)
  twitterDataFrame['RetweetCount'] = twitterDataFrame['RetweetCount'].map(lambda x: x if pandas.notnull(x) else 0)
  twitterDataFrame['FavouriteCount'] = twitterDataFrame['FavouriteCount'].map(lambda x: x if pandas.notnull(x) else 0)
  twitterDataFrame['Hashtags'] = twitterDataFrame['Hashtags'].map(lambda x: True if pandas.notnull(x) else False)
  twitterDataFrame['URL'] = twitterDataFrame['URL'].map(lambda x: True if pandas.notnull(x) else False)
  twitterDataFrame['MediaURL'] = twitterDataFrame['MediaURL'].map(lambda x: True if pandas.notnull(x) else False)
  twitterDataFrame['MediaType'] = twitterDataFrame['MediaType'].map(lambda x: x if pandas.notnull(x) else False)
  twitterDataFrame['UserMentionID'] = twitterDataFrame['UserMentionID'].map(lambda x: True if pandas.notnull(x) else False)
  twitterDataFrame['PossiblySensitive'] = twitterDataFrame['PossiblySensitive'].map(lambda x: x if pandas.notnull(x) else 'NoData')

当我打印信息时,这就是我得到的。

None
<class 'pandas.core.frame.DataFrame'>
Int64Index: 21836 entries, 0 to 21835
Data columns (total 17 columns):
CreatedAt                   21836 non-null object
ActualTweet                 21836 non-null object
InReplyToStatusID           21836 non-null bool
InReplyToUserID             21836 non-null bool
UserID                      21836 non-null object
RetweetCount                21836 non-null object
FavouriteCount              21836 non-null object
Hashtags                    21836 non-null bool
URL                         21836 non-null bool
MediaURL                    21836 non-null bool
MediaType                   21836 non-null object
UserMentionID               21836 non-null bool
PossiblySensitive           21836 non-null object
Language                    21836 non-null object
Classifier                  21836 non-null object
TweetLength                 21836 non-null object
CreatedAtForCalculations    21836 non-null object
dtypes: bool(6), object(11)None

对于较小的数据集,不过这样可行,我们得到:

None
<class 'pandas.core.frame.DataFrame'>
Int64Index: 8978 entries, 0 to 8977
Data columns (total 17 columns):
CreatedAt                   8978 non-null datetime64[ns]
ActualTweet                 8978 non-null object
InReplyToStatusID           8978 non-null bool
InReplyToUserID             8978 non-null bool
UserID                      8978 non-null int64
RetweetCount                8978 non-null int64
FavouriteCount              8978 non-null int64
Hashtags                    8978 non-null bool
URL                         8978 non-null bool
MediaURL                    8978 non-null bool
MediaType                   8978 non-null object
UserMentionID               8978 non-null bool
PossiblySensitive           8978 non-null object
Language                    8978 non-null object
Trustworthy                 8978 non-null int64
TweetLength                 8978 non-null int64
CreatedAtForCalculations    8978 non-null datetime64[ns]
dtypes: bool(6), datetime64[ns](2), int64(5), object(4)None

有谁知道为什么这是我可以做些什么来解决它?

2 个答案:

答案 0 :(得分:2)

这是将现有框架的列从object转换为更实用的一种很好的方法。通常,您不需要执行此操作,因为read_csv之类的内容会为您进行转换。但如果你有混合值,那么这些转换可能会失败。

请参阅文档here

In [13]: data = """21-01-2014,1
   ....: 31x01x2014,foo
   ....: 01-01-2014,2
   ....: hello,3"""

In [14]: df = pd.DataFrame.from_csv( StringIO(data), index_col=None, header=None )

In [15]: df
Out[15]: 
            0    1
0  21-01-2014    1
1  31x01x2014  foo
2  01-01-2014    2
3       hello    3

In [16]: df.dtypes
Out[16]: 
0    object
1    object
dtype: object

In [17]: df.convert_objects(convert_dates='coerce',convert_numeric=True)
Out[17]: 
           0   1
0 2014-01-21   1
1        NaT NaN
2 2014-01-01   2
3        NaT   3

In [18]: df.convert_objects(convert_dates='coerce',convert_numeric=True).dtypes
Out[18]: 
0    datetime64[ns]
1           float64
dtype: object

这将转换“看起来&#39;喜欢日期和数字。您可能希望将此限制为某些列并且更具选择性。它只会尝试object类型列。此外,这是在cython中实现的,所以会非常快。

答案 1 :(得分:1)

也许有更好的解决方案如何找到无法转换的值。

这是我使用apply()

的解决方案

我的测试数据:

import pandas as pd
from StringIO import StringIO

data = '''21-01-2014
31x01x2014
01-01-2014
"Hello World"'''

df = pd.DataFrame.from_csv( StringIO(data), index_col=None, header=None )

print df

'''
             0
0   21-01-2014
1   31x01x2014
2   01-01-2014
3  Hello World
'''

我创建的函数使用datetime.datetime.strptime()try/except来捕获(并打印)错误的日期。

from datetime import datetime

def test_datetime(x):
    try:
        datetime.strptime(x, "%d-%M-%Y")
    except:
        print 'incorect:', x

然后我可以使用apply()来测试列

中的所有值
df[0].apply(test_datetime)

'''
incorect: 31x01x2014
incorect: Hello World
'''

但我可以在之前的功能中添加return True/False

from datetime import datetime

def test_datetime(x):
    try:
        datetime.strptime(x, "%d-%M-%Y")
        return False
    except:
        return True

以这种方式使用它并获取索引

的数据
print df[ df[0].apply(test_datetime) ]

'''
             0
1   31x01x2014
3  Hello World
'''

并在此行上运行其他功能

df[ df[0].apply(test_datetime) ] = '01-01-2000'

print df

'''
            0
0  21-01-2014
1  01-01-2000
2  01-01-2014
3  01-01-2000
'''