0

buildings320 万行のテーブルがあります。(バランスの取れた) Paneldataとして処理するには、このテーブルを 11 の異なる期間に拡張する必要があります。これは、すべてのオブジェクトについて、11 の異なる年 (2000 年から 2010 年) を観察する必要があることを意味します。ピリオドは次のように呼ばれる必要があります。

2000
2001
...
2009
2010

テーブル定義

CREATE TABLE public.buildings
(
  gid integer NOT NULL DEFAULT nextval('buildings_gid_seq'::regclass),
  osm_id character varying(11),
  name character varying(48),
  type character varying(16),
  geom geometry(MultiPolygon,4326),
  centroid geometry(Point,4326),
  gembez character varying(50),
  gemname character varying(50),
  krsbez character varying(50),
  krsname character varying(50),
  pv boolean,
  gr smallint,
  capac double precision,
  instdate date,
  pvid integer,
  dist double precision,
  gemewz integer,
  n500 integer,
  ibase double precision,
  popden integer,
  instp smallint,
  b2000 double precision,
  b2001 double precision,
  b2002 double precision,
  b2003 double precision,
  b2004 double precision,
  b2005 double precision,
  b2006 double precision,
  b2007 double precision,
  b2008 double precision,
  b2009 double precision,
  b2010 double precision,
  ibase_id integer[],
  ibase_dist integer[],
  CONSTRAINT buildings_pkey PRIMARY KEY (gid)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE public.buildings
  OWNER TO postgres;

CREATE INDEX build_centroid_gix
  ON public.buildings
  USING gist
  (st_transform(centroid, 31467));

CREATE INDEX buildings_geom_idx
  ON public.buildings
  USING gist
  (geom);

Rでの回帰分析にデータを使用したい。

ibase_idの配列ですgidibase_distオブジェクトまでの距離を含む関連配列gidです。2 つの配列の長さは常に同じです。

gid配列内の は のレコードに属し、オブジェクトの中心buildingsから 500m の半径内にありcentroid、かつ pv=TRUE です (これはdistinstdateinstpcapac&pvidがであることを意味しますNOT NULL)。

SELECT a.gid AS buildid, array_agg(b.gid) AS ibase_id, array_agg(round(ST_Distance(ST_Transform(a.centroid, 31467), ST_Transform(b.centroid, 31467))::integer)) AS ibase_dist
  FROM buildings a
  LEFT JOIN (SELECT * FROM buildings WHERE pv=TRUE) AS b ON ST_DWithin(ST_Transform(a.centroid, 31467), ST_Transform(b.centroid, 31467), 500.0)
      AND a.gid <> b.gid
  GROUP BY a.gid

例:

ibase_id: {3075528,409073,322311,226643,833798,322344,226609};

ibase_dist {290,293,398,494,411,381,384}

UPDATE buildings
SET ibase=SUM(1/s)
FROM unnest(SELECT ibasedist FROM buildings WHERE (SELECT instp 
       FROM buildings 
       WHERE gid IN unnest(ibase_id))<year) s

各期間について、配列のエントリのみが考慮され、その年はパネル データの観測期間よりも前でした。(最初に配列を連結する必要があるため、上記のクエリはまだ機能しません)現在、2 つの配列はすべての年の情報を保持しています。そのため、各期間に追加する必要があると考えたので、パネルデータに展開した後、ibase各レコード (11x 3,2 百万) を計算します。

回帰分析にすべての列は必要ありません。乗算のパフォーマンスが劇的に向上する場合は、行に固執することができます (基本的にはジオメトリ列を除外します)。

   gid integer NOT NULL DEFAULT nextval('buildings_gid_seq'::regclass),
      gembez character varying(50),
      gemname character varying(50),
      krsbez character varying(50),
      krsname character varying(50),
      pv boolean,
      gr smallint,
      capac double precision,
      dist double precision,
      gemewz integer,
      n500 integer,
      ibase double precision,
      popden integer,
      instp smallint,
      b2000 double precision,
      b2001 double precision,
      b2002 double precision,
      b2003 double precision,
      b2004 double precision,
      b2005 double precision,
      b2006 double precision,
      b2007 double precision,
      b2008 double precision,
      b2009 double precision,
      b2010 double precision,
      ibase_id integer[],
      ibase_dist integer[],
      CONSTRAINT buildings_pkey PRIMARY KEY (gid)
    )
    WITH (
      OIDS=FALSE

ソリューションアプローチ

periods11 の異なる期間を含む 2 番目のテーブルを作成し、このテーブルに table を乗算するという基本的なアイデアがありましたbuildings。これを実装する方法がわからない。残念ながら、私は R の経験があまりなく、R のデータベース インターフェイスをまだ使用していません。

Visual C++ ビルド 1800、64 ビットおよび R x64 3.2.1 でコンパイルされた PostgreSQL 9.5beta2 での作業

4

2 に答える 2

1

基本的に、パネル データ セットは、時間列として各レコードの年を繰り返す長い形式のデータです。現在の構造はワイド形式です。R はこの非常に大きなデータセットを変換できますが、PostGreSQL はそのエンジンを使用してユニオン クエリですべての年をまとめてスタックし、結果セットを R に渡すことができます。ジオメトリ オブジェクトや配列などの一部のデータ型は、R データ型に正しく変換されない場合があることに注意してください。それらを削除するか、文字列/数値型に変換してください。

以下は、積み上げられた年を持つ SQL UNION クエリです。ibase_idおよびibase_distまたは「乗算」の側面で何を意味するのかよくわかりませんが、Year対応する列に列が追加されbます。RPostGreSQLモジュール経由で R スクリプトに呼び出してもらいます。

import("RPostgreSQL")

# CREATE CONNECTION     
drv <- dbDriver("PostgreSQL")
con <- dbConnect(drv, dbname = "postgres",
                 host = "localhost", port = ####,
                 user = "username", password = "password")

strSQL <- "SELECT '2000' As year,  gid, gembez, gemname, krsbez,
                 krsname, pv, gr, capac, dist, gemewz, n500
                 popden, instp, b2000 As b, (1/ibase_dist) As ibase
           FROM public.buildings
           INNER JOIN
                (SELECT a.gid AS buildid, 
                        SUM(round(ST_Distance(
                                              ST_Transform(a.centroid, 31467),  
                                              ST_Transform(b.centroid, 31467)
                                  )::integer)) AS ibase_dist
               FROM buildings a
               LEFT JOIN buildings b 
                      ON ST_DWithin(ST_Transform(a.centroid, 31467), 
                                    ST_Transform(b.centroid, 31467), 500.0)
                    AND a.gid <> b.gid
               WHERE b.pv=True AND b.instp < a.instp
               GROUP BY a.gid) AS distSum
           ON public.buildings.gid = distSum.buildid
           WHERE public.buildings.instp = 2000

           UNION

           ...other SELECT statements for years 2001-2010..."              

# IMPORT QUERY RESULTSET INTO DATAFRAME
df <- dbGetQuery(con, strSQL)

# CLOSE CONNECTION
dbDisconnect(con)

ただし、大きなデータセットの操作に必要なRAMがあることを確認してください。それに応じてメモリを割り当てる必要がある場合があります。SELECTまたは、すべてを一度にロードするのではなく、毎年のステートメントを成長するデータフレーム オブジェクトに繰り返し追加することもできます。

# ...SAME CONNECTION SETUP AS ABOVE...

years = c('2000', '2001', '2002', '2003', '2004', '2005', 
          '2006', '2007', '2008', '2009', '2010')

# CREATES LIST OF YEAR DATA FRAME
dfList = lapply(years, 
                function(y) {
                # NOTICE CONCATENATION OF Y IN SELECT STATEMENT 
                strSQL <- paste0("SELECT '", y, "' As year,  gid, gembez, gemname, krsbez,
                                         krsname, pv, gr, capac, dist, gemewz, n500, 
                                         popden, instp, b", y, ", As b, (1/ibase_dist) As ibase, 
                                  FROM public.buildings
                                  INNER JOIN
                                    (SELECT a.gid AS buildid, 
                                          SUM(round(ST_Distance(
                                              ST_Transform(a.centroid, 31467),  
                                              ST_Transform(b.centroid, 31467)
                                          )::integer)) AS ibase_dist
                                     FROM buildings a
                                     LEFT JOIN buildings b 
                                     ON ST_DWithin(ST_Transform(a.centroid, 31467), 
                                                   ST_Transform(b.centroid, 31467), 500.0)
                                     AND a.gid <> b.gid
                                     WHERE b.pv=True AND b.instp < a.instp
                                     GROUP BY a.gid) AS distSum
                                  ON public.buildings.gid = distSum.buildid
                                  WHERE public.buildings.instp =", y)
                dbGetQuery(con, strSQL)                               
                })

# APPEND LIST OF DATA FRAMES INTO ONE LARGE DATA FRAME              
df <- do.call(rbind, dfList)

# REMOVE PREVIOUS LIST FOR MEMORY RESOURCES
rm(dfList)

# CLOSE CONNECTION
dbDisconnect(con)
于 2016-02-07T01:39:13.613 に答える
0

期間を含む一時テーブル t1 とのクロス JOIN を使用して、Paneldata テーブルを作成しました。

CREATE TABLE public.t1
(
  period smallint
)
WITH (
  OIDS=FALSE
);



CREATE TABLE paneldata AS
(SELECT * 
FROM t1 CROSS JOIN 
    (SELECT gid, 
    gemname, 
    gembez, 
    krsname,
    krsbez,
    pv,
    gr,
    capac,
    dist,
    gemewz,
    n500,
    popden,
    instp
    FROM buildings) AS test
ORDER BY gid)
于 2016-02-16T12:59:50.163 に答える