2

私は R での単純な実装の経験は豊富ですが、R を介した SQL との通信や並列プログラミングは初めてです (今日まで、これら 2 つのことの経験はありません)。ブログやフォーラムなどからのプロンプトを使用して、以下のコードを作成しました。

library(doParallel) 

library(RMySQL) 

library(DBI)

library(foreach)

cl <- makeCluster(12)

registerDoParallel(cl)

Postcodecsv <- read.csv("C:/Users/Henry Crosby/Desktop/PostcodeLatLong.csv")

mydb = dbConnect(MySQL(), user='****', password="******* ****", 

dbname='population_distance', host='****.**.*.*')

dbListFields(mydb,'Postcodes')

foreach (a = 1:120000, .combine="rbind") %dopar% {

  Done <- dbGetQuery(mydb, paste("select FID, Postcode2, (6371 * acos( cos( 
radians( ",Postcodecsv[a,6],"))*cos(radians(latitude))*cos(radians(Longitude)-radians(",Postcodecsv[a,5],"))+sin(radians(",Postcodecsv[a,6],") )* sin( radians( latitude ) ) ) ) AS distance from Postcodes having distance < 2 ORDER BY distance",sep=" "))

write.table(Done,file="C:/Users/Henry Crosby/Desktop/2km.csv",append=TRUE, col.names=FALSE, sep=",")

  } 

この計算は for ループで機能しますが、永遠に時間がかかります (これを大きなデータセットに適用する必要があります!)。上記のコードを実行すると、以下のエラーが発生します。エラーが発生する理由と、それを回避する方法を教えてください。

{ のエラー: タスク 1 が失敗しました - 「関数 "dbGetQuery" が見つかりませんでした」

4

2 に答える 2

1

問題は、foreach がmydbオブジェクトを自動エクスポートしていることですが、ソケット接続を含むオブジェクトをシリアル化してプロセス間でコピーすることができないため、正しく機能しません。

clusterEvalQ各ワーカーで作成する関数を使用してクラスター ワーカーを初期化することをお勧めしますmydb。次のようなものを試すことができます:

clusterEvalQ(cl, {
  library(RMySQL)
  mydb <- dbConnect(MySQL(), user='****', password="******* ****",
                    dbname='population_distance', host='****.**.*.*')
  NULL
})

mydbただし、 foreach オプションを使用して foreachが自動エクスポートしないようにする必要があり.noexport="mydb"ます。foreach.verbose=TRUEオプションを使用して、どのオブジェクトがワーカーに自動エクスポートされているかを確認することもできます。

于 2016-01-07T22:21:49.593 に答える
0

R を使用して sql から csv への移行を処理するのはなぜですか? 完全な SQL ソリューションを検討し、処理をデータベース エンジンに任せます。具体的には、Postcodes テーブルと PostcodeLatLong csv データを結合します (もちろん、MySQL データベースにインポートします)。次に、MySQL のOUTFILE機能を使用します。dbGetQuery()全体として、並列ループなしで 1 回だけ実行する必要があります。

expotCSV <- dbGetQuery("SELECT FID, Postcode2, (6371 * acos( cos( 
                     radians(Postcodecsv.col6))*cos(radians(latitude))*cos(radians(Longitude)-
                     radians(Postcodecsv.col5))+sin(radians(Postcodecsv.col6))* sin(radians(latitude)))) 
                     AS distance     

              FROM Postcodes 
              INNER JOIN PostcodeLatLong ON csv.joinfield = PostcodeLatLong.joinfield
              HAVING distance < 2 
              ORDER BY distance

              INTO OUTFILE 'C:/Users/Henry Crosby/Desktop/2km.csv' 
              FIELDS ENCLOSED BY '\"' 
              TERMINATED BY ';' 
              ESCAPED BY '\"' 
              LINES TERMINATED BY '\\r\\n';")

joinfield課題は、2 つのテーブル間の or 関係を見つけることです。ただし、SQL では、クエリがリストされたテーブル間の合計組み合わせセットを返すデカルト積またはクロス結合(一見無関係なテーブルの場合) も許可されます。いくつかのフィルタリング句で where 句を使用できます。

FROM Postcodes, PostcodeLatLong 
WHERE Postcodes.somefactor = "..." AND PostcodeLatLong.somefactor = "..."

または、MySQL のCROSS JOIN(ON 句のない JOIN)

FROM Postcodes CROSS JOIN PostcodeLatLong 
WHERE Postcodes.somefactor = "..." AND PostcodeLatLong.somefactor = "..."
于 2016-01-08T03:09:00.513 に答える