从 SQL 数据库导入表并按日期过滤行时,将 Pandas 列解析为 Datetime
Posted
技术标签:
【中文标题】从 SQL 数据库导入表并按日期过滤行时,将 Pandas 列解析为 Datetime【英文标题】:Parse a Pandas column to Datetime when importing table from SQL database and filtering rows by date 【发布时间】:2013-04-30 23:55:13 【问题描述】:我有一个DataFrame
,其列名为date
。我们如何将“日期”列转换/解析为DateTime
对象?
我使用 sql.read_frame()
从 Postgresql 数据库中加载了日期列。 date
列的一个示例是 2013-04-04
。
我要做的是选择数据框中的所有行,其日期列在特定时期内,例如在2013-04-01
之后和2013-04-04
之前。
我在下面的尝试给出了错误'Series' object has no attribute 'read'
尝试
import dateutil
df['date'] = dateutil.parser.parse(df['date'])
错误
AttributeError Traceback (most recent call last)
<ipython-input-636-9b19aa5f989c> in <module>()
15
16 # Parse 'Date' Column to Datetime
---> 17 df['date'] = dateutil.parser.parse(df['date'])
18
19 # SELECT RECENT SALES
C:\Python27\lib\site-packages\dateutil\parser.pyc in parse(timestr, parserinfo, **kwargs)
695 return parser(parserinfo).parse(timestr, **kwargs)
696 else:
--> 697 return DEFAULTPARSER.parse(timestr, **kwargs)
698
699
C:\Python27\lib\site-packages\dateutil\parser.pyc in parse(self, timestr, default, ignoretz, tzinfos, **kwargs)
299 default = datetime.datetime.now().replace(hour=0, minute=0,
300 second=0, microsecond=0)
--> 301 res = self._parse(timestr, **kwargs)
302 if res is None:
303 raise ValueError, "unknown string format"
C:\Python27\lib\site-packages\dateutil\parser.pyc in _parse(self, timestr, dayfirst, yearfirst, fuzzy)
347 yearfirst = info.yearfirst
348 res = self._result()
--> 349 l = _timelex.split(timestr)
350 try:
351
C:\Python27\lib\site-packages\dateutil\parser.pyc in split(cls, s)
141
142 def split(cls, s):
--> 143 return list(cls(s))
144 split = classmethod(split)
145
C:\Python27\lib\site-packages\dateutil\parser.pyc in next(self)
135
136 def next(self):
--> 137 token = self.get_token()
138 if token is None:
139 raise StopIteration
C:\Python27\lib\site-packages\dateutil\parser.pyc in get_token(self)
66 nextchar = self.charstack.pop(0)
67 else:
---> 68 nextchar = self.instream.read(1)
69 while nextchar == '\x00':
70 nextchar = self.instream.read(1)
AttributeError: 'Series' object has no attribute 'read'
df['date'].apply(dateutil.parser.parse)
给我错误AttributeError: 'datetime.date' object has no attribute 'read'
df['date'].truncate(after='2013/04/01')
给出错误TypeError: can't compare datetime.datetime to long
df['date'].dtype
返回dtype('O')
。它已经是datetime
对象了吗?
【问题讨论】:
请在您的date
专栏中发布一些示例!因为 pandas 实际上应该识别一个日期时间对象,所以查看该列的实际格式会很有帮助
@RyanSaxe 我使用 sql.read_frame()
从 Postgresql 数据库中加载了日期列。 date
列的一个示例是 2013-04-04
。如何检查列的 dtype?
df['date'].dtype
返回dtype('O')
【参考方案1】:
Pandas 知道对象日期时间,但是当您使用某些导入函数时,它会被视为字符串。因此,您需要做的是确保将列设置为日期时间类型而不是字符串。然后,您可以进行查询。
df['date'] = pd.to_datetime(df['date'])
df_masked = df[(df['date'] > datetime.date(2012,4,1)) & (df['date'] < datetime.date(2012,4,4))]
【讨论】:
【参考方案2】:你可能需要apply
,比如:
df['date'] = df['date'].apply(dateutil.parser.parse)
如果没有该专栏的示例,我不能保证这会奏效,但在这个方向上的一些东西应该可以帮助您继续前进。
【讨论】:
谢谢,我试过df['date'].apply(dateutil.parser.parse)
,它给出了错误。 AttributeError: 'datetime.date' object has no attribute 'read'
。该列的一个示例是2013-04-04
。整个数据框是使用 sql.readframe()
从 PostgreSQL 数据库加载的。【参考方案3】:
pandas 已经将其读取为 datetime
对象!所以你想要的是选择两个日期之间的行,你可以通过屏蔽来做到这一点:
df_masked = df[(df.date > '2012-04-01') & (df.date < '2012-04-04')]
因为你说你因为某种原因从字符串中得到一个错误,试试这个:
df_masked = df[(df.date > datetime.date(2012,4,1)) & (df.date < datetime.date(2012,4,4))]
【讨论】:
df = df[df.date > '2012-01-01']
给我一个错误TypeError: can't compare datetime.date to str
。
我一直用这个!这很奇怪......您的问题与我提出的问题非常相似,我得到了这个答案并且它有效。 See it here
是的..当我手动创建数据框时它可以工作...但是如果我使用sql.read_frame
从SQL数据库创建数据框,'2012-01-01'
会被视为字符串?
尝试df[df.date > dateutil.parser.parse('2013-01-01') ]
给了我TypeError: can't compare datetime.datetime to datetime.date
df.date 是类型对象,但我认为 2013-01-01
被视为字符串。当我使用dateutil.parser.parse()
如上面的cmets 时,错误从str
变为datetime.date
【参考方案4】:
不要将 datetime.date
与 Pandas pd.Timestamp
混淆
“熊猫datetime
系列”包含pd.Timestamp
元素,不 datetime.date
元素。 Pandas 的推荐解决方案:
s = pd.to_datetime(s) # convert series to Pandas
mask = s > '2018-03-10' # calculate Boolean mask against Pandas-compatible object
热门答案有问题:
@RyanSaxe 接受的答案的第一次尝试不起作用;第二个答案是低效的。 从 Pandas v0.23.0 开始,@Keith 高度赞成的答案不起作用;它给了TypeError
。
任何好的 Pandas 解决方案必须确保:
-
该系列是 Pandas
datetime
系列,而不是 object
dtype。
datetime
系列与兼容对象进行比较,例如pd.Timestamp
,或格式正确的字符串。
这是一个带有基准测试的演示,证明一次性转换成本可以通过一次操作立即抵消:
from datetime import date
L = [date(2018, 1, 10), date(2018, 5, 20), date(2018, 10, 30), date(2018, 11, 11)]
s = pd.Series(L*10**5)
a = s > date(2018, 3, 10) # accepted solution #2, inefficient
b = pd.to_datetime(s) > '2018-03-10' # more efficient, including datetime conversion
assert a.equals(b) # check solutions give same result
%timeit s > date(2018, 3, 10) # 40.5 ms
%timeit pd.to_datetime(s) > '2018-03-10' # 33.7 ms
s = pd.to_datetime(s)
%timeit s > '2018-03-10' # 2.85 ms
【讨论】:
【参考方案5】:您应该遍历项目并独立解析它们,然后构造一个新列表。
df['date'] = [dateutil.parser.parse(x) for x in df['date']]
【讨论】:
以上是关于从 SQL 数据库导入表并按日期过滤行时,将 Pandas 列解析为 Datetime的主要内容,如果未能解决你的问题,请参考以下文章
将excel数据导入sql server数据库表并在gridview中显示