2017-05-14 8 views
4

Rで生成したベクトルをsqliteテーブルに新しい列として追加しようとしています。このため私はdplyrを使用したかったです(この投稿hereに従ってdbplyrパッケージとともに最新の開発バージョンをインストールしました)。私が試したこと:sqliteデータベースに列を追加する

library(dplyr) 
library(DBI) 

#creating initial database and table 
dbcon  <- dbConnect(RSQLite::SQLite(), "cars.db") 
dbWriteTable(dbcon, name = "cars", value = cars) 
cars_tbl <- dplyr::tbl(dbcon, "cars") 

#new values which I want to add as a new column 
new_values <- sample(c("A","B","C"), nrow(cars), replace = TRUE) 

#attempt to add new values as column to the table in the database 
cars_tbl %>% mutate(new_col = new_values) #not working 

これを実現する簡単な方法は何ですか(dplyrでは必要ありません)。

+0

dplyrは入力データの変更を避けるように設計されています。しかし、既存のテーブル/データフレームと 'mutate()'変換に基づいて新しいテーブルを作成することができます。 – krlmlr

答えて

3

dyplrでこれを行う方法は知られていませんが、直接RSQLiteで行うことができます。問題は実際にはRSQLiteではありませんが、私はどのようにリストをmutateに渡すのか分かりません。あなたのコードでは、次のようなものが動作することに注意してください。

cars_tbl %>% mutate(new_col = another_column/3.14) 

とにかく、私の代わりです。私はおもちゃcarsデータフレームを作成しました。

cars <- data.frame(year=c(1999, 2007, 2009, 2017), model=c("Ford", "Toyota", "Toyota", "BMW")) 

私は接続を開き、実際にテーブルを作成し、

dbcon <- dbConnect(RSQLite::SQLite(), "cars.db") 
dbWriteTable(dbcon, name = "cars", value = cars) 

は、新しい列を追加し、確認し、

dbGetQuery(dbcon, "ALTER TABLE cars ADD COLUMN new_col TEXT") 
dbGetQuery(dbcon, "SELECT * FROM cars") 
    year model new_col 
1 1999 Ford <NA> 
2 2007 Toyota <NA> 
3 2009 Toyota <NA> 
4 2017 BMW <NA> 

そして、あなたは新しい列を更新することができますが、トリッキーなだけあなたはwhereという文を入力する必要があります。この場合は、私は年を使います。一意のインデックスとして

new_values <- sample(c("A","B","C"), nrow(cars), replace = TRUE) 
new_values 
[1] "C" "B" "B" "B" 

dbGetPreparedQuery(dbcon, "UPDATE cars SET new_col = ? where year=?", 
        bind.data=data.frame(new_col=new_values, 
             year=cars$year)) 

dbGetQuery(dbcon, "SELECT * FROM cars") 
    year model new_col 
1 1999 Ford  C 
2 2007 Toyota  B 
3 2009 Toyota  B 
4 2017 BMW  B 

、あなたは常にrownames(cars)を使用することができますが、あなたはあなたのデータフレームで、その後、あなたのテーブルの列として追加する必要があります。 @krlmlrの提案後

EDIT:確かにはるかに良い代わりにdbGetPreparedQuery非推奨のdbExecuteを使用して、コメント

dbExecute(dbcon, "UPDATE cars SET new_col = :new_col where year = :year", 
      params=data.frame(new_col=new_values, 
          year=cars$year)) 

編集:私は、しかし、たとえ、数日前にこのことについて考えていませんでしたSQLiteで、rowidを使用できます。私はこれを試して、それは動作します。

dbExecute(dbcon, "UPDATE cars SET new_col = :new_col where rowid = :id", 
      params=data.frame(new_col=new_values, 
          id=rownames(cars))) 

テーブル内のROWIDがあなたのrownamesと同じであることを確認する必要がありますが、とにかくあなたはいつもあなたのROWIDを次のように得ることができます:

dbGetQuery(dbcon, "SELECT rowid, * FROM cars") 
    rowid year model new_col 
1  1 1999 Ford  C 
2  2 2007 Toyota  B 
3  3 2009 Toyota  B 
4  4 2017 BMW  B 
+0

'dbGetPreparedQuery()'は推奨されていませんので、代わりに 'dbExecute(...、params = data.frame())'を使用できるはずです。 – krlmlr

+0

ありがとう@krlmlr! – lrnzcig

+0

答えをありがとう。あなたの解決策に1つの問題があります。一意の値を持つデータベーステーブル内の唯一のフィールドは 'rownames(df)'にほぼ対応するidです。違いは異なるデータタイプです。データベースでは、型は 'ident'であり、Rでは' character'です。私も '数値 'で試しましたが、どちらもうまくいきません。どうすれば修正できますか? – Alex

関連する問題