Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python pandas.read_sql和解释指定为周的日期_Python_Sql_Pandas - Fatal编程技术网

Python pandas.read_sql和解释指定为周的日期

Python pandas.read_sql和解释指定为周的日期,python,sql,pandas,Python,Sql,Pandas,我有一个这种格式的SQL表,我想将其读取并转换为一个timeseries y (year) w (week) d (some data) 2009 1 10 2009 2 15 ... 做这件事的好方法是什么 我知道read_sql的parse_dates参数,或者使用DatetimeIndex手动设置索引。我无法理解如何使用周数据进行此操作。我试过以下方法。谢谢 # gives NaT for year & week: d

我有一个这种格式的SQL表,我想将其读取并转换为一个timeseries

y (year)  w (week)   d (some data)
2009      1          10
2009      2          15
...
做这件事的好方法是什么

我知道read_sql的parse_dates参数,或者使用DatetimeIndex手动设置索引。我无法理解如何使用周数据进行此操作。我试过以下方法。谢谢

# gives NaT for year & week:
df = pd.read_sql("SELECT y, w, d FROM t",
                 db, parse_dates={"y":"%Y", "w":"%U"})

# gives wrong dates for yw - e.g. all 2009-01-01:
df = pd.read_sql("SELECT CONCAT(y,'/',w) as yw, d FROM t",
                 db, parse_dates={"yw": "%Y/%U"})

# throws DateParseError exception:
df = pd.read_sql("SELECT CONCAT(y,'W',w) as yw, d FROM t",
                 db)
df.index = pd.DatetimeIndex(df.yw)

实际上,我认为最优雅的方式是用SQL执行转换:

sql = "SELECT DATE_ADD(MAKEDATE(y, 1), INTERVAL w WEEK) as date, d FROM test.t"
df = pd.read_sql(sql, engine)
print(df)
屈服

         date   d
0  2009-01-08  10
1  2009-01-15  15
        date   d
0 2009-01-08  10
1 2009-01-15  15
由于AFAIK Pandas不提供任何开箱即用的设施,无法将年数和周数转换为日期,因此在Python中进行等效操作需要更多的锅炉板。当然,您可以使用循环和datetime模块将数字逐个转换为datetime.datetime对象

更快的方法是使用NumPy的datetime64和timedelta64数据类型作为NumPy数组执行日期算术:

sql = "SELECT y, w, d FROM t"
df = pd.read_sql(sql, engine)

date = (df['y'].astype('<i8')-1970).view('<M8[Y]')
delta = (df['w'].astype('<i8')*7).view('<m8[D]')
df['date'] = date+delta
df = df[['date', 'd']]
print(df)
编辑:基于Hadi在评论中的回答,还可以使用MySQL计算SQL中的日期:

产生

         date   d
0  2008-12-29  10
1  2009-01-05  15
注意,根据%v,表示

后来,模式3意味着

Mode    First day of week   Range   Week 1 is the first week …
3       Monday              1-53    with 4 or more days this year
对于含义为“今年有4天或更多天”的模式值 根据ISO 8601:1988对周进行编号

因此,如果您希望周数与ISO 8601:1988一致,那么对于STR_to_DATE,您应该使用%v或%u,而不是%v或%u


请注意,我上面的第一个答案并没有将这一周解释为ISO 8601周数;它只计算每周从1月1日起的7天。

也许可以使用SQL来:从t@unutbu中选择DATE\u ADDMAKEDATEy,1,INTERVAL w week,d。@unutbu,谢谢你的建议,这应该会有用。然而,我假设有一种更优雅的Pythonic方法来实现这一点。我发现这也是可行的:pd.read_sqlSELECT CONCATy,':',w,':1'作为dt,d FROM t,db,parse_dates={dt:%Y:%U:%w}。这样,解析在Python端进行。它仍然在SQL中使用CONCAT,所以我不确定它是否比您建议的更好。哦,这太聪明了!请注意,您的方法给出的结果与我的不同-因为%Y:%U:%w被解析为表示从周一开始的一年中的第n周,而我的方法从1月1日开始计算n*7天。我现在接受您的答案,但可能更好的答案是alter on found:Hadi,发布并接受您的解决方案是可以的-您的解决方案与ISO-8601对周数的定义一致,而我的不一致。更正:要在Python中将周数解析为ISO-8601:1988周数,您可能需要使用%V而不是%U。要在MySQL中解析相同的周数,您需要使用%V。
Week (01..53), where Monday is the first day of the week; WEEK() mode 3; used with %x
Mode    First day of week   Range   Week 1 is the first week …
3       Monday              1-53    with 4 or more days this year