मेरे पास एक data.table
है जिसे मुझे सूचियों में विभाजित करने की आवश्यकता है। यहाँ एक नमूना डेटा सेट है:
testSet <- data.table(A = 1:2, B = 4:5, C = rep(7:8, times = 50),
D = 9:10, E = 15:16, F = 24:25, G = 27:28,
H = 29:30, I = 32:33, J = 35:36, K = 1:50)
जैसा कि आप देख सकते हैं, इसमें 11 कॉलम हैं, जिनमें से प्रत्येक संख्यात्मक है। मुझे 10 कॉलम में मानों से विभाजित करने की आवश्यकता है ताकि सूचियों की एक सूची बनाई जा सके। मैंने निम्नलिखित कार्यात्मक कोड (संदर्भ के लिए मैकबुक एयर) बनाया है:
system.time(testSetLists <- split(testSet,
list(testSet[["A"]], testSet[["B"]], testSet[["C"]],
testSet[["D"]], testSet[["E"]], testSet[["F"]],
testSet[["G"]], testSet[["H"]], testSet[["I"]],
testSet[["J"]])))
> user system elapsed
0.759 0.109 0.731
यह पूरी तरह से काम करता है और मुझे बिल्कुल वही आउटपुट देता है जिसकी मुझे आवश्यकता है। हालांकि, जब मैं केवल एक कॉलम में संख्या सीमा बढ़ाता हूं, जैसे A
निम्न डेटा सेट में:
testSet <- data.table(A = 1:5, B = 4:5, C = rep(7:8, times = 50),
D = 9:10, E = 15:16, F = 24:25, G = 27:28,
H = 29:30, I = 32:33, J = 35:36, K = 1:50)
system.time(testSetLists <- split(testSet,
list(testSet[["A"]], testSet[["B"]], testSet[["C"]],
testSet[["D"]], testSet[["E"]], testSet[["F"]],
testSet[["G"]], testSet[["H"]], testSet[["I"]],
testSet[["J"]])))
> user system elapsed
2.139 0.301 2.054
आप देख सकते हैं कि A
में केवल 3 मान जोड़कर निष्पादित करने का समय प्रसंस्करण समय को तीन गुना कर देता है। अब क्या होता है जब मैं B
, D
, और J
में और मान जोड़ता हूं, जैसे?
testSet <- data.table(A = 1:5, B = 4:9, C = rep(7:8, times = 50),
D = 9:14, E = 15:16, F = 24:25, G = 27:28,
H = 29:30, I = 32:33, J = 35:56, K = 1:50)
system.time(testSetLists <- split(testSet,
list(testSet[["A"]], testSet[["B"]], testSet[["C"]],
testSet[["D"]], testSet[["E"]], testSet[["F"]],
testSet[["G"]], testSet[["H"]], testSet[["I"]],
testSet[["J"]])))
> user system elapsed
179.356 21.311 176.562
जैसा कि आप देख सकते हैं, यह समाधान अस्थिर है जब मेरे पास प्रत्येक कॉलम में 100 या इतने ही अद्वितीय डेटा बिंदु होते हैं।
मैं इस फ़ंक्शन का उपयोग करके सभी खाली सूचियों को हटा सकता हूं:
testSetLists <- testSetLists[sapply(testSetLists, function(x) dim(x)[1]) > 0]
मेरा प्रश्न यह है: मैं अत्यधिक उच्च CPU समय के बिना समान इनपुट कैसे ले सकता हूं और समान आउटपुट कैसे प्राप्त कर सकता हूं? R के भीतर कोई भी विकल्प टेबल पर है।
2 जवाब
ऐसा प्रतीत होता है कि गणना में इतना समय लगा क्योंकि split
प्रदान किए गए कारकों में से प्रत्येक संयोजन को निर्धारित करने का प्रयास करता है। हालांकि, drop=TRUE
तर्क सेट किया जा सकता है, इसलिए केवल उन संयोजनों को रखा जाता है जिनमें तत्व होते हैं। आपके अंतिम डेटासेट पर, मेरे पीसी पर:
system.time(testSetLists <- split(testSet,testSet[,.SD,.SDcols=names(testSet)[1:10]]))
# user system elapsed
#128.111 0.343 128.930
system.time(testSetLists <- split(testSet,testSet[,.SD,.SDcols=names(testSet)[1:10]],drop=TRUE))
# user system elapsed
# 0.048 0.000 0.048
यह भी ध्यान दें कि मैंने उस समय मैन्युअल रूप से लिखने के बजाय, विभाजन को इंगित करने वाले कॉलम कैसे लिए।
हाल ही में data.table को अपना split
तरीका मिला है। यह कॉलम नामों को विभाजित करने के लिए स्वीकार कर सकता है। f
तर्क के लिए पूर्ण कॉलम पास करने की कोई आवश्यकता नहीं है, जैसा कि data.frame के मामले में होता है। यह split.data.frame
के विपरीत, समूहीकरण के क्रम को भी सुरक्षित रख सकता है।
library(data.table)
suppressWarnings( # OP data raises recycling warning
testSet <- data.table(A = 1:5, B = 4:9, C = rep(7:8, times = 50),
D = 9:14, E = 15:16, F = 24:25, G = 27:28,
H = 29:30, I = 32:33, J = 35:56, K = 1:50)
)
system.time(dropF <- split(testSet, testSet[,.SD,.SDcols=names(testSet)[1:10]]))
# user system elapsed
#371.684 4.032 115.058
system.time(dropT <- split(testSet, testSet[,.SD,.SDcols=names(testSet)[1:10]], drop=TRUE))
# user system elapsed
# 0.304 0.004 0.097
system.time(byDropT <- split(testSet, by=names(testSet)[1:10], drop=TRUE, sorted=TRUE))
# user system elapsed
# 0.180 0.000 0.061
all.equal(
dropT[sort(names(dropT))],
byDropT
)
#[1] TRUE
1.9.7 संस्करण स्थापित करने के लिए उपयोग करें:
install.packages("data.table", type = "source", repos = "https://Rdatatable.github.io/data.table")