2017-10-23 18 views
5

के भीतर निकटतम मूल्य ढूँढना मैं प्रत्येक इलाज वाले अवलोकनों के लिए निकटतम मूल्य खोजने का प्रयास कर रहा हूं। डेटा के रूप में (1.2M ओ बीएस से एक आंशिक डेटा) इस प्रकार देखो:डेटा.table

> dta 
    id treatment  score 
1: 5   0 0.02381024 
2: 10   0 0.05428605 
3: 22   0 0.02118124 
4: 27   0 0.01495214 
5: 45   0 0.01877916 
6: 50   0 0.02120360 
7: 58   0 0.02207263 
8: 60   0 0.02807019 
9: 61   0 0.05432927 
10: 65   1 0.59612077 
11: 68   0 0.02482168 
12: 72   1 0.14582400 
13: 73   0 0.02371670 
14: 77   0 0.02608826 
15: 87   0 0.06852409 
16: 88   0 0.07473471 
17: 94   0 0.07160314 
18: 97   0 0.02040747 
19: 104   1 0.09878789 
20: 108   0 0.02421807 

प्रत्येक इलाज किया टिप्पणियों के लिए (यानी, उपचार = 1) मैं एक अनुपचारित अवलोकन प्राप्त करना चाहते हैं (यानी, उपचार = 0) के साथ निकटतम स्कोर और चुने हुए अवलोकन को अन्य इलाज अवलोकनों के मिलान के लिए अपरिहार्य के रूप में चिह्नित करें।

उदाहरण के लिए, पहले इलाज अवलोकन (पंक्ति 10) आईडी = 88 (पंक्ति 16), पंक्ति 12 से पंक्ति 17 तक मेल खाएगा, और इसी तरह।

smpl_treated = dta[treatment == 1] 
smpl_untreated = dta[treatment == 0] 

n_tmp = nrow(smpl_treated) 
matched_id = matrix(0, n_tmp, 1) 

smpl_tmp = smpl_untreated 

for (i in 1:nrow(smpl_treated)) { 

    x = smpl_treated[i]$score 

    setkey(smpl_tmp, score) 
    tmp = smpl_tmp[J(x), roll = "nearest"] 
    matched_id[i] = tmp[[1]] 
    smpl_tmp = smpl_tmp[id != tmp[[1]]] 

} 

matched_smpl = smpl_untreated[id %in% matched_id] 

> matched_smpl 
    id treatment  score 
1: 87   0 0.06852409 
2: 94   0 0.07160314 
3: 88   0 0.07473471 

कोई सुझाव यह एक data.table के भीतर हो या तेज पाश बनाने बनाने के लिए: वर्तमान में मैं floowing पाश चल रहा हूँ? मूल 1.2 एम obs के साथ लूप 2 घंटे से अधिक लेता है। आपकी सहायता के लिए अग्रिम धन्यवाद!

+0

मान लीजिए आप निम्नलिखित 5 नमूने होगा: {(आईडी = 1, उपचार = 0, स्कोर = 0), (आईडी = 2 , उपचार = 1, स्कोर = 0.1), (आईडी = 3, उपचार = 1, स्कोर = 0.2), (आईडी = 4, उपचार = 1, स्कोर = 0.3), (आईडी = 5, उपचार = 0, स्कोर = 0.4)}। दूसरे शब्दों में, आपके पास दो इलाज न किए गए अवलोकनों के बीच 3 व्यवहार किए गए अवलोकन हैं। इस मामले में, क्या नक्शे क्या है? – Ben

+0

मेरे संदर्भ में, ऐसा नहीं होगा। यदि ऐसा होता है, हालांकि, शायद मुझे विपरीत करना चाहिए - इसका मुख्य उद्देश्य इलाज और इलाज न किए गए अवलोकनों का संतुलित नमूना प्राप्त कर रहा है। – jayc

उत्तर

1

इस का उपयोग करते हुए बताते हैं the already accepted answer of denis (मैं अन्यथा एक सीधा सरल उपाय नहीं दिख रहा है) वास्तविकdata.table वाक्यविन्यास की संभावनाएं, उदाहरण के लिए, setkey() के बजाय on पैरामीटर का उपयोग करते समय।

# determine the minimum number of treated and untreated cases 
n <- min(dta[treatment == 0L, .N], dta[treatment == 1L, .N]) 
# order by descending score 
mdt <- dta[order(-score)][ 
    # and pick the ids of the top n treated and untreated cases 
    # so that the highest untreated score match the highest treated score, 
    # the 2nd highest untreated the 2nd highest treated and so forth 
    , .(id0 = head(.SD[treatment == 0L, id], n), id1 = head(.SD[treatment == 1L, id], n))] 
mdt 
id0 id1 
1: 88 65 
2: 94 72 
3: 87 104 
# join the ids two times to show the data of the treated and untreated cases 
dta[dta[mdt, on = .(id==id0)], on = .(id = id1)] 
id treatment  score i.id i.treatment i.score 
1: 65   1 0.59612077 88   0 0.07473471 
2: 72   1 0.14582400 94   0 0.07160314 
3: 104   1 0.09878789 87   0 0.06852409 
+0

यह समाधान मेरा से बहुत बेहतर है, और वास्तव में नौकरी करता है (ऐसा नहीं लगता है कि उपचार और गैर उपचार डेटा में अलग-अलग स्कोर सीमा होती है)। – denis

+0

@denis साझा करने के लिए धन्यवाद आपकी अच्छी टिप्पणी के लिए धन्यवाद। हालांकि, आपके समाधान सही दिशा में इंगित किया! – Uwe

1

यदि आप अपनी डेटा तालिका ऑर्डर करते हैं, सबसेट बनाते हैं और विलय की शक्ति का उपयोग करते हैं तो मुझे समाधान मिल सकता है। सुनिश्चित नहीं हैं कि यह सबसे अच्छा समाधान है, लेकिन यह मैं क्या समझ में आ आप क्या करना चाहते के लिए काम करने लगता है, और यह तेजी से अपने पाश से पक्का हो जाएगा:

library(data.table) 
dta <- data.table(id = c(5,10,22,27,45,50,58,60,61,65,68,72,73,77,87,88,94,97,104,108), 
        treatment = c(0, 0 ,0 ,0, 0, 0, 0 ,0 , 0 , 1, 0 ,1 ,0, 0 ,0 ,0 ,0 ,0 ,1 ,0), 
        score = c(0.02381024, 0.05428605, 0.02118124, 0.01495214, 0.01877916, 0.02120360, 
          0.02207263, 0.02807019, 0.05432927, 0.59612077, 0.02482168, 0.14582400, 
          0.02371670, 0.02608826, 0.06852409, 0.07473471, 0.07160314, 0.02040747, 
          0.09878789, 0.02421807)) 

setkey(dta, score) # order by score 
treated_nbr <- dta[treatment == 1, .N] # just to simplify the next line 

selecteddata <- 
    dta[treatment == 0, 
     .SD[(.N - treated_nbr + 1):.N, 
      .(correspid = id, 
      correspscore = score, 
      id = dta[treatment == 1, id])]] 
यहाँ

हम गैर का आदेश दिया की एक ही नंबर ले इलाज किया व्यक्ति (.N-treated_nbr+1):.N) इतना है कि वे आदेश दिया एक के सबसे करीब स्कोर है, और हम इलाज किया एक (id = dta[,.SD[treatment == 1,id]])

setkey(selecteddata, id) 
setkey(dta, id) 
selecteddata[dta] # do the merging 

सुनिश्चित नहीं हैं कि यह वास्तव में है कि आप क्या चाहते की आईडी पर आईडी विलय, क्योंकि मैं एहसास हुआ कि यह केवल तभी काम करता है जब आपके इलाज किए गए स्कोर इलाज वाले लोगों से अधिक न हों (जो आपके उदाहरण में मामला है)। आप एक शर्त समाधान स्कोर गैर इलाज किया लोगों की तुलना में अधिक के साथ इलाज व्यक्ति के लिए केवल प्रस्तावित उपयोग करने के लिए जोड़ सकते हैं, और नहीं तो बाकी काम

+0

यह बहुत मदद करता है - धन्यवाद, डेनिस! – jayc

संबंधित मुद्दे