Python 是否有方法将sqlalchemy查询中的数据附加到for循环中的pandas数据帧?
我目前正在for循环中从一个sqlalchemy查询中提取数据,该循环将不同的设备id/accon_时间对作为变量进行迭代 其思想是一次提取一个设备/时间对的数据,并将其附加到一个数据帧以供以后处理 其原因是批量甚至小批量提取数据会为我们的数据库触发高IOPS警报 起初,我尝试在循环中使用df.append(),但是我从查询对象中得到了一个类型错误 TypeError:无法连接“类”类型的对象 sqlalchemy.orm.query.query”;只有Series和DataFrame OBJ有效 然后,我决定尝试将查询对象转换为序列,然后将序列转换为数据帧:Python 是否有方法将sqlalchemy查询中的数据附加到for循环中的pandas数据帧?,python,pandas,sqlalchemy,Python,Pandas,Sqlalchemy,我目前正在for循环中从一个sqlalchemy查询中提取数据,该循环将不同的设备id/accon_时间对作为变量进行迭代 其思想是一次提取一个设备/时间对的数据,并将其附加到一个数据帧以供以后处理 其原因是批量甚至小批量提取数据会为我们的数据库触发高IOPS警报 起初,我尝试在循环中使用df.append(),但是我从查询对象中得到了一个类型错误 TypeError:无法连接“类”类型的对象 sqlalchemy.orm.query.query”;只有Series和DataFrame OBJ有
for i in range(len(df)):
dev_id = (df.iloc[i]['dev_id'])
accon_time = (df.iloc[i]['accon_time'])
new_session = Session()
gps_qry = new_session.query(GPS).filter(GPS.dev_id == dev_id).filter(GPS.accon_time == accon_time). \
filter(GPS.tm_time.between(20190620145813, 20190620151400))
gps_qry = [repr(x) for x in gps_qry]
ser_2 = pd.Series(data=gps_qry)
#This part here is to split the comma seperated values in the series into 3 seperate columns:
df_2 = ser_2.apply(lambda x: pd.Series([val.split('=')[1] for val in x[1:-1].split(',')]))
df_2 = df_2.append(gps_qry, ignore_index=True)
df_2.columns = ['dev_id', 'accon_time', 'tm_time']
print(df_2)
我期待着这样的事情:
dev_id accon_time tm_time
0 'A' 'B' 'C'
1 'D' 'E' 'F'
2 'G' 'H' 'I'
但结果却是:
dev_id accon_time tm_time
0 'A' 'B' 'C'
1 'D,E,F...' NaN NaN
我不太确定发生了什么,但这是我最接近解决这个问题的方法,因为其他方法都会引发类型错误,但是您可以使用
sqlalchemy
和pandas
的组合,方法是访问使用ORM构建的原始查询,并按照@furas的建议将其传递给read\u sql
。通过这种方式,您可以继续使用ORM创建查询
例如:
gps\u qry=new\u session.query(gps).filter(gps.dev\u id==dev\u id).filter(gps.accon\u time==accon\u时间)\
过滤器(GPS.tm_时间间隔(20190620145813、20190620151400))
gps\u df=pd.read\u sql(gps\u qry.statement,con=db.engine)
##或
gps\u df=pd.read\u sql(str(gps\u qry),con=db.engine)
或在循环中使用:
df_2=pd.DataFrame()
对于范围内的i(len(df)):
dev_id=(df.iloc[i]['dev_id'])
accon_time=int((df.iloc[i]['accon_time']))##更新为使用python int。
新建会话=会话()
gps\u qry=new\u session.query(gps).filter(gps.dev\u id==dev\u id).filter(gps.accon\u time==accon\u time)\
过滤器(GPS.tm_时间间隔(20190620145813、20190620151400))
###在每个循环中追加
gps\u df=pd.read\u sql(str(gps\u qry),con=db.engine)
df_2=pd.concat([df_2,gps_-df],轴=0,排序=False,忽略索引=True)
打印(df_2)
pandas
有pd.read\u sql()
,pd.read\u sql\u query()
直接从数据库读取。使用print()
查看变量中的内容。它应该可以帮助您看到问题。为什么要使用repr()
?转换某些东西是一种奇怪的方法。您可以尝试gps\u qry=list(gps\u qry)
或直接ser\u 2=pd.Series(data=list(gps\u qry))
,也许您将不需要df.apply()
@furas我已经实际尝试过使用pd.read\u sql()和pd.read\u sql\u query(),但以前总是会收到这样的错误消息“nota executable object”@furas using repr()解决我之前遇到的一个错误,即我的数据表不可订阅。使用list()实际上会引发相同的错误对于循环的每次迭代,您仍然可以使用.append
甚至pd.concat
和gps\u df
。使用.append或pd.concat都会引发此错误“不支持numpy.int64类型的Python值”您是否尝试将开发id
转换为int
?我更新了答案来考虑这个问题,因为一些数据库不会接受NUMPY/BANDAS整数类型。另外,会计时间的格式是什么?如果是整数,我也会使用相同的方法。accon_time是一个整数,但是dev_ID的ID值实际上是字符串,因为它们是字母和数字的组合。这就是问题所在。令人惊叹的!非常感谢您的修复和向我展示如何实际使用pd.read_sql()