3

私は大きなデータセットを持っています。他の dta ファイル (Criteria_data) に格納されている値を使用して、データ セット (Big_data) をサブセット化する必要があります。最初に問題を示します。

   **Big_data**                           **Criteria_data**
====================      ================================================
  lon        lat             4_digit_id   minlon  maxlon  minlat  maxlat
-76.22      44.27              0765       -78.44  -77.22  34.324  35.011
-67.55      33.19              6161       -66.11  -65.93  40.32   41.88
    .......                                   ........
 (over 1 million obs)                    (271 observations)        
====================      ================================================

入札データを次のようにサブセット化する必要があります。

use Big_data

preserve
keep if (-78.44<lon<-77.22) & (34.324<lat<35.011)
save data_0765, replace
restore

preserve
keep if (-66.11<lon<-65.93) & (40.32<lat<41.88)
save data_6161, replace
restore

....

(1) Stata でのサブセット化のための効率的なプログラミングとは? (2) 不等式は正しく書かれていますか?

4

3 に答える 3

4

1) データのサブセット化

メイン ファイルに 400,000 件の観測があり、参照ファイルに 300 件あるため、約 1.5 分かかります。メイン ファイルの 2 倍の観測値でこれをテストすることはできません。RAM が不足しているため、コンピューターがクロールするからです。

戦略には、参照緯度と経度を保持するために必要な数の変数を作成することが含まれます (OP の場合は 271*4 = 1084。Stata IC 以上でこれを処理できます。 を参照してくださいhelp limits)。これには、いくつかの再形成と追加が必要です。次に、条件を満たすビッグデータ ファイルの観測を確認します。

clear all
set more off

*----- create example databases -----

tempfile bigdata reference

input ///
lon        lat   
-76.22      44.27
-66.0      40.85 // meets conditions
-77.10     34.8 // meets conditions
-66.00    42.0 
end

expand 100000

save "`bigdata'"
*list

clear all

input ///
str4 id   minlon  maxlon  minlat  maxlat
"0765"       -78.44  -75.22  34.324  35.011
"6161"       -66.11  -65.93  40.32   41.88
end

drop id
expand 150
gen id = _n

save "`reference'"
*list


*----- reshape original reference file -----

use "`reference'", clear

tempfile reference2

destring id, replace
levelsof id, local(lev)

gen i = 1
reshape wide minlon maxlon minlat maxlat, i(i) j(id) 

gen lat = .
gen lon = .

save "`reference2'"


*----- create working database -----

use "`bigdata'"

timer on 1
quietly {
    forvalues num = 1/300 {
        gen minlon`num' = .
        gen maxlon`num' = .
        gen minlat`num' = .
        gen maxlat`num' = .
    }
}
timer off 1

timer on 2
append using "`reference2'"
drop i
timer off 2

*----- flag observations for which conditions are met -----

timer on 3
gen byte flag = 0
foreach le of local lev {
    quietly replace flag = 1 if inrange(lon, minlon`le'[_N], maxlon`le'[_N]) & inrange(lat, minlat`le'[_N], maxlat`le'[_N])
}
timer off 3

*keep if flag
*keep lon lat

*list

timer list

関数はinrange()、OP の厳密な不等式 (関数テスト <=、>=) を満たすために、最小値と最大値を事前に調整する必要があることを意味します。

おそらく、 を使用したいくつかの拡張expand、相関関係の使用、およびby(データが長い形式である) ことで、速度が向上する可能性があります。今の私には完全には明らかではありません。プレーンな Stata モードでもっと良い方法があると確信しています。マタはさらに良いかもしれません。

(joinbyもテストされましたが、やはり RAM が問題でした。)

編集

完全なデータベースではなくチャンクで計算を行うと、RAM の問題が大幅に改善されます。120 万回の観測を含むメイン ファイルと 300 回の観測を含む参照ファイルを使用すると、次のコードはすべての作業を約 1.5 分で実行します。

set more off

*----- create example big data -----

clear all

set obs 1200000
set seed 13056

gen lat = runiform()*100
gen lon = runiform()*100

local sizebd `=_N' // to be used in computations

tempfile bigdata
save "`bigdata'"

*----- create example reference data -----

clear all

set obs 300
set seed 97532

gen minlat = runiform()*100
gen maxlat = minlat + runiform()*5

gen minlon = runiform()*100
gen maxlon = minlon + runiform()*5

gen id = _n

tempfile reference
save "`reference'"


*----- reshape original reference file -----

use "`reference'", clear

destring id, replace
levelsof id, local(lev)

gen i = 1
reshape wide minlon maxlon minlat maxlat, i(i) j(id) 
drop i

tempfile reference2
save "`reference2'"


*----- create file to save results -----

tempfile results
clear all
set obs 0

gen lon = .
gen lat = .

save "`results'"


*----- start computations -----

clear all

* local that controls # of observations in intermediate files
local step = 5000 // can't be larger than sizedb

timer clear

timer on 99
forvalues en = `step'(`step')`sizebd' {

    * load observations and join with references
    timer on 1
    local start = `en' - (`step' - 1)
    use in `start'/`en' using "`bigdata'", clear
    timer off 1

    timer on 2
    append using "`reference2'"
    timer off 2

    * flag observations that meet conditions
    timer on 3
    gen byte flag = 0
    foreach le of local lev {
        quietly replace flag = 1 if inrange(lon, minlon`le'[_N], maxlon`le'[_N]) & inrange(lat, minlat`le'[_N], maxlat`le'[_N])
    }
    timer off 3

    * append to result database
    timer on 4
    quietly {
        keep if flag
        keep lon lat
        append using "`results'"
        save "`results'", replace
    }
    timer off 4

}
timer off 99

timer list
display "total time is " `r(t99)'/60 " minutes"

use "`results'"
browse

2) 不平等

不等式が正しいかどうかを尋ねます。それらは実際には合法であり、Stata は文句を言わないことを意味しますが、結果はおそらく予期しないものです。

次の結果は驚くべきものに思えるかもしれません。

. display  (66.11 < 100 < 67.93)
1

式が true (つまり 1) と評価されるのはどうしてですか? Stata はまずどちらが真かを評価66.11 < 100し、次にどちらが真かを判断1 < 67.93します。

意図した式は次のとおりです (そして、Stata は希望どおりに動作します)。

. display  (66.11 < 100) & (100 < 67.93)
0

関数に依存することもできますinrange()

次の例は、前の説明と一致しています。

. display  (66.11 < 100 < 0)
0

Stata は66.11 < 100どちらが真 (つまり 1) であるかを確認し1 < 0、偽 (つまり 0) である をフォローアップします。

于 2014-04-09T00:18:16.907 に答える
2

これは Roberto のデータ設定を使用します。

clear all

set obs 1200000
set seed 13056

gen lat = runiform()*100
gen lon = runiform()*100

local sizebd `=_N' // to be used in computations

tempfile bigdata
save "`bigdata'"

*----- create example reference data -----

clear all

set obs 300
set seed 97532

gen minlat = runiform()*100
gen maxlat = minlat + runiform()*5

gen minlon = runiform()*100
gen maxlon = minlon + runiform()*5

gen id = _n

tempfile reference
save "`reference'"


timer on 1
levelsof id, local(id_list)

foreach id of local id_list {
    sum minlat if id==`id', meanonly
    local minlat = r(min)
    sum maxlat if id==`id', meanonly
    local maxlat = r(max)

    sum minlon if id==`id', meanonly
    local minlon = r(min)
    sum maxlon if id==`id', meanonly
    local maxlon = r(max)

    preserve
        use if (inrange(lon,`minlon',`maxlon') & inrange(lat,`minlat',`maxlat')) using "`bigdata'", clear
        qui save data_`id', replace
    restore
}

timer off 1
于 2014-04-10T00:53:03.313 に答える