Pandas 将数据帧转换为内存中类似文件的对象?

Pandas 将数据帧转换为内存中类似文件的对象?,pandas,psycopg2,Pandas,Psycopg2,我每天将大约200-250万条记录加载到Postgres数据库中 然后,我使用pd.read_sql读取这些数据,将其转换为数据帧,然后执行一些列操作和一些较小的合并。我正在将修改后的数据另存为一个表,供其他人使用 当我做pd.to_sql时,它需要永远。如果我保存一个csv文件并在Postgres中使用COPY FROM,整个过程只需要几分钟,但是服务器在一台单独的机器上,在那里传输文件是一件痛苦的事情 使用psycopg2,看起来我可以使用copy_expert从批量复制中获益,但仍然使用p

我每天将大约200-250万条记录加载到Postgres数据库中

然后,我使用pd.read_sql读取这些数据,将其转换为数据帧,然后执行一些列操作和一些较小的合并。我正在将修改后的数据另存为一个表,供其他人使用

当我做pd.to_sql时,它需要永远。如果我保存一个csv文件并在Postgres中使用COPY FROM,整个过程只需要几分钟,但是服务器在一台单独的机器上,在那里传输文件是一件痛苦的事情

使用psycopg2,看起来我可以使用copy_expert从批量复制中获益,但仍然使用python。如果可能的话,我想避免编写实际的csv文件。我可以在内存中使用熊猫数据帧执行此操作吗

下面是我的pandas代码的一个示例。如果可能的话,我想添加copy_expert或其他东西来加快保存这些数据的速度

    for date in required_date_range:
        df = pd.read_sql(sql=query, con=pg_engine, params={'x' : date})
        ...
        do stuff to the columns
        ...
        df.to_sql('table_name', pg_engine, index=False, if_exists='append',  dtype=final_table_dtypes)
有人能帮我写示例代码吗?我更喜欢使用熊猫,在记忆中这样做会很好。如果没有,我将只写一个csv临时文件,并这样做

编辑-这是我的最终代码。每个日期(数百万行)只需要几百秒,而不是几个小时

to_sql=“”使用CSV头从STDIN复制%s”“”


Python模块
io
()为类似文件的对象提供了必要的工具

import io

# text buffer
s_buf = io.StringIO()

# saving a data frame to a buffer (same as with a regular file):
df.to_csv(s_buf)
编辑。 (我忘了)为了以后从缓冲区读取,应该将其位置设置为开始:

s_buf.seek(0)
我不熟悉
psycopg2
,但根据
copy\u expert
copy\u from
两种方法,都可以使用,例如:

cur.copy_from(s_buf, table)

(对于Python 2,请参见。)

我在实现来自ptrj的解决方案时遇到问题

我认为问题源于将缓冲区的位置设置到末尾

见下文:

from StringIO import StringIO
df = pd.DataFrame({"name":['foo','bar'],"id":[1,2]})
s_buf = StringIO()
df.to_csv(s_buf)
s_buf.__dict__

# Output
# {'softspace': 0, 'buflist': ['foo,1\n', 'bar,2\n'], 'pos': 12, 'len': 12, 'closed': False, 'buf': ''}
请注意,pos位于12。我必须将pos设置为0,以便后续的copy_from命令能够工作

s_buf.pos = 0
cur = conn.cursor()
cur.copy_from(s_buf, tablename, sep=',')
conn.commit()

我不知道psycopg2,但您可以尝试这样的方法:
s_buf=io.StringIO()
df.to_csv(s_buf)
,它将您的df存储在类似缓冲区的文件中。然后可能是从(s_buf,…)复制当前的
cur.copy\u,而不是
copy\u expert
!不过我还是保留了复印件。当我使用纯pandas.to_sql时,它只花了大约100秒而不是10000秒。做一个真实的回答,这样我就可以接受。很高兴我能帮上忙。谢谢。此外,我还循环查看每个日期以查询该日期。每次我再次连接到数据库时。是否有更好的方法不必连接/重新连接每个环路?就像我连接一次,然后在循环过程中更改查询?我不确定是否理解,但你不能只查询一次整个内容(范围内的所有日期)。如果这个太大,那么可以分块查询。我想它会在数据框中添加另一个带有日期的列。然后,如果不需要,您可以删除此列,或者选择并使用子框架,或者按日期分组并在组中迭代。或者,如果您想完全避免
pd.read\u sql
,可以使用
copy\u expert
/
copy\u to
将数据复制到字符串缓冲区,并使用
pd.read\u csv
将其加载到数据帧。这只是我的想法。
AttributeError:“\io.StringIO”对象没有属性“write\u cells”
我在周末运行了该代码,没有收到任何错误。星期一我到办公室的时候,我的桌子空了,糟透了。我最终写了临时的csv文件,它完全可以工作。因此,如果我对csv(s_buf)和s_buf.pos=0执行操作,那么它将在不编写csv的情况下工作?@a_bigbadwolf@trench Good point!这是文件/流缓冲区的标准行为(即不是熊猫的过错)。我只是忘了把它包括在内,我道歉。将位置设置为开头的惯用方法是运行
sbuf.seek(0)
s_buf.pos = 0
cur = conn.cursor()
cur.copy_from(s_buf, tablename, sep=',')
conn.commit()