web-dev-qa-db-ja.com

Pandas update sql

各行を反復せずにデータフレームからSQL更新を実行する方法はありますか? postgresqlデータベースがあり、データベース内のテーブルをデータフレームから更新するには、psycopg2を使用して次のようにします。

con = psycopg2.connect(database='mydb', user='abc', password='xyz')
cur = con.cursor()

for index, row in df.iterrows():
    sql = 'update table set column = %s where column = %s'
    cur.execute(sql, (row['whatver'], row['something']))
con.commit()

しかし一方で、SQLからテーブルを読み取るか、データフレーム全体をSQLに書き込む(更新場所なし)場合は、pandasとsqlalchemyを使用します。

engine = create_engine('postgresql+psycopg2://user:pswd@mydb')
df.to_sql('table', engine, if_exists='append')

To_sqlを使用して「ワンライナー」を持っているだけですばらしい。 pandasからpostgresqlへのupdate-whereを実行するのに似たものはありませんか?または、上記で行ったように各行を反復することによってそれを行う唯一の方法です。各行を介してそれを行うには非効率的な方法?

34
darkpool

最終テーブルの正確なレプリカであり、実行ごとに消去される一時テーブルを考えてみましょう。

engine = create_engine('postgresql+psycopg2://user:pswd@mydb')
df.to_sql('temp_table', engine, if_exists='replace')

sql = """
    UPDATE final_table AS f
    SET col1 = t.col1
    FROM temp_table AS t
    WHERE f.id = t.id
"""

with engine.begin() as conn:     # TRANSACTION
    conn.execute(sql)
33
Parfait

データベーステーブルを更新する条件として、dfに格納されている外部データを使用しているようです。可能であれば、なぜ1行のSQL更新をしないのですか?

小さなデータベースで作業している場合(データ全体をpython dataframeオブジェクトにロードしても殺されない)、あなたはcanread_sqlを使用してロードした後、データフレームを確実に条件付きで更新します。その後、キーワードarg if_exists="replace"を使用して、DBテーブルを新しい更新されたテーブルに置き換えることができます。

df = pandas.read_sql("select * from your_table;", engine)

#update information (update your_table set column = "new value" where column = "old value")
#still may need to iterate for many old value/new value pairs
df[df['column'] == "old value", "column"] = "new value"

#send data back to sql
df.to_sql("your_table", engine, if_exists="replace")

Pandasは強力なツールであり、最初はSQLのサポートが制限されていましたが、小さな機能でした。時間が経つにつれて、人々はpandasを唯一のデータベースインターフェースソフトウェアとして使用しようとしています。pandasデータベースの相互作用についてですが、常に新しい機能に取り組んでいる人が大勢います。 https://github.com/pandas-dev/pandas/issues

9

これまでのところ、pandas sqlコネクターがupdateデータベースへのスケーラブルな方法で使用できる場合は見ていません。データを作成するのは良いアイデアのように思えるかもしれませんが、実際には、運用上の作業のためにスケーリングしません。

私がお勧めするのは、データフレーム全体をCSVとしてダンプすることです

df.to_csv('filename.csv', encoding='utf-8')

次に、 [〜#〜] copy [〜#〜] を使用してデータベースにCSVをロードします。PostgreSQLの場合は LOAD DATA INFILE を使用します。

パンダがデータを操作しているときに、対象のテーブルに他の変更を加えない場合は、テーブルにロードするだけです。

並行性の問題がある場合、データをステージングテーブルにロードし、それを使用してプライマリテーブルを更新する必要があります。

後者の場合、プライマリテーブルには、pandasの変更が最新であるか、データベースの変更を残すかを判断できるように、いつ最新の変更が行われたかを通知する日時が必要です。 。

1
firelynx

最初に方程式に基づいてdfを更新し、次にdfをデータベースに保存して、if_exists = 'replace'を使用して同じテーブルに保存するのはなぜだろうと思っていました。

0
nabaz

SQLをシミュレートするために複数の条件に基づいてパンダを更新する必要がある場合:

UPDATE table WHERE A > 7 AND B > 69

単に.locを使用できます

>>> df
      A   B    C
0     2  40  800
1     1  90  600
2     6  80  700
3  1998  70   55
4     1  90  300
5     7  80  700
6     4  20  300
7  1998  20    2
8     7  10  100
9  1998  60    2

>>> df.loc[(df['A'] > 7) & (df['B'] > 69) , 'C'] = 75

これにより、「A」> 7および「B」> 69の「C」= 75が設定されます。

0
GavinBelson