में सूचियों का उपयोग करके मैं कुछ एचटीएमएल दस्तावेज़ों में सहेजे गए डेटा के निष्कर्षण को समानांतर करने की कोशिश कर रहा हूं और इसे डेटा.फ्रेम (कुछ लाख दस्तावेजों, इसलिए समांतरता की उपयोगिता) में संग्रहीत करने की कोशिश कर रहा हूं।फोरैच आर
पहले चरण में, जहां मैं कतार पंजीकृत करता हूं, उस मशीन पर, मैं HTML फ़ाइलों का एक सबसेट चुनता हूं और उनसे लापरवाही से read_html फ़ंक्शन (rvest पैकेज से, मैंने XML से समान फ़ंक्शन का भी प्रयास किया है पैकेज लेकिन मुझे स्मृति रिसाव की समस्याएं मिल रही थीं) कई एचटीएमएल पृष्ठों की सामग्री को संग्रहित करने वाली एक अनूठी सूची प्राप्त करने के लिए।
फिर मैं इस सूची में एक इटरेटर का उपयोग करता हूं ताकि इसे फोरच को खिलाने के लिए छोटे हिस्से प्राप्त हो सकें।
पूर्वानुमान के अंदर मैं डेटा.फ्रेम (HTML) टेम्पलेट का उपयोग कर रहा हूं (HTML_table फ़ंक्शन और कुछ मूल डेटा मैनिपुलेशन का उपयोग कर रहा हूं) और मैं एक सूची लौटाता हूं जिसका तत्व साफ डेटा हैं। फ्रेम।
मैंने जीत 8 पर डूस्नो बैकएंड और यूबंटू 16.04 पर डूरेडिस दोनों का उपयोग करने का प्रयास किया है।
पहले मामले में रिक्त सूचियों की एक सूची लौटा दी जाती है जबकि दूसरी तरफ मेमोरी मैपिंग की त्रुटि फेंक दी जाती है; आप प्रश्न के बहुत नीचे ट्रेसबैक पा सकते हैं।
मेरी समझ के लिए जो मैं कोर को भेज रहा हूं, वह मुझे समझने के लिए व्यवहार नहीं कर रहा है। मैंने चारों ओर इकट्ठा किया है कि सूची वस्तु केवल पॉइंटर्स का एक सेट हो सकती है लेकिन मैं इसकी पुष्टि करने में सक्षम नहीं हूं; शायद यह मुद्दा हो सकता है? क्या एकाधिक HTML पृष्ठों के डेटा को "encapsulate" करने के लिए "सूची तरीका" का कोई विकल्प है?
नीचे आप इस मुद्दे को पुन: उत्पन्न करने के लिए कुछ कोड पा सकते हैं। मैं ओवरफ्लो ढेर करने के लिए बिल्कुल नया हूं, समांतर प्रोग्रामिंग के लिए नया और आर प्रोग्रामिंग के लिए बिल्कुल नया: सुधार के लिए कोई सलाह स्वागत है। सभी को अग्रिम धन्यवाद।
library(rvest)
library(foreach)
#wikipedia pages of olympic medalist between 1992 and 2016 are
# downloaded for reproducibility
for(i in seq(1992, 2016, by=4)){
html = paste("https://en.wikipedia.org/wiki/List_of_", i, "_Summer_Olympics_medal_winners", sep="")
con = url(html)
htmlCode = readLines(con)
writeLines(htmlCode, con=paste(i, "medalists", sep="_"))
close(con)
}
#declaring the redis backend (doSNOW code is also included below)
#note that I am using the package from
#devtools::install_github("bwlewis/doRedis") due to a "nodelay error"
#(more info on that here: https://github.com/bwlewis/doRedis/issues/24)
# if it is not your case please drop the nodelay and timeout options
#Registering cores ---Ubuntu---
cores=2
library('doRedis')
options('redis:num'=TRUE)
registerDoRedis("jobs", nodelay=FALSE)
startLocalWorkers(n=cores, "jobs", timeout=2, nodelay=FALSE)
foreachOpt <- list(preschedule=FALSE)
#Registering cores ---Win---
#cores=2
#library("doSNOW")
#registerDoSNOW(makeCluster(cores, type = "SOCK"))
#defining the iterator
iterator <- function(x, ...) {
i <- 1
it <- idiv(length(x), ...)
if(exists("chunks")){
nextEl <- function() {
n <- nextElem(it)
ix <- seq(i, length=n)
i <<- i + n
x[ix]
}
}else{
nextEl <- function() {
n <- nextElem(it)
ix <- seq(i, i+n-1)
i <<- i + n
x[ix]
}
}
obj <- list(nextElem=nextEl)
class(obj) <- c(
'ivector', 'abstractiter','iter')
obj
}
#reading files
names_files<-list.files()
html_list<-lapply(names_files, read_html)
#creating iterator
ChunkSize_html_list<-2
iter<-iterator(html_list, chunkSize=ChunkSize_html_list)
#defining expanding list (thanks StackOverflow and many thanks to
#JanKanis's answer : http://stackoverflow.com/questions/2436688/append-an-object-to-a-list-in-r-in-amortized-constant-time-o1 )
expanding_list <- function(capacity = 10) {
buffer <- vector('list', capacity)
length <- 0
methods <- list()
methods$double.size <- function() {
buffer <<- c(buffer, vector('list', capacity))
capacity <<- capacity * 2
}
methods$add <- function(val) {
if(length == capacity) {
methods$double.size()
}
length <<- length + 1
buffer[[length]] <<- val
}
methods$as.list <- function() {
b <- buffer[0:length]
return(b)
}
methods
}
#parallelized part
clean_data<-foreach(ite=iter, .packages=c("itertools", "rvest"), .combine=c,
.options.multicore=foreachOpt, .options.redis=list(chunkSize=1)) %dopar% {
temp_tot <- expanding_list()
for(g in 1:length(ite)){
#extraction of data from tables
tables <- html_table(ite[[g]], fill=T, header = T)
for(i in 1:length(tables)){
#just some basic data manipulation
temp<-lapply(tables, function(d){d[nrow(d),]})
temp_tot$add(temp)
rm(temp)
gc(verbose = F)
}
}
#returning the list of cleaned data.frames to the foreach
temp_tot$as.list()
}
त्रुटि फेंक दिया जब redis बैकएंड का उपयोग कर:
*** caught segfault ***
address 0x60, cause 'memory not mapped'
Traceback:
1: .Call("xml2_doc_namespaces", PACKAGE = "xml2", doc)
2: doc_namespaces(doc)
3: xml_ns.xml_document(x)
4: xml_ns(x)
5: xpath_search(x$node, x$doc, xpath = xpath, nsMap = ns, num_results = Inf)
6: xml_find_all.xml_node(x, ".//table")
7: xml2::xml_find_all(x, ".//table")
8: html_table.xml_document(ite[[g]], fill = T, header = T)
9: html_table(ite[[g]], fill = T, header = T)
10: eval(expr, envir, enclos)
11: eval(.doRedisGlobals$expr, envir = .doRedisGlobals$exportenv)
12: doTryCatch(return(expr), name, parentenv, handler)
13: tryCatchOne(expr, names, parentenv, handlers[[1L]])
14: tryCatchList(expr, classes, parentenv, handlers)
15: tryCatch({ lapply(names(args), function(n) assign(n, args[[n]], pos = .doRedisGlobals$exportenv)) if (exists(".Random.seed", envir = .doRedisGlobals$exportenv)) { assign(".Random.seed", .doRedisGlobals$exportenv$.Random.seed, envir = globalenv()) } tryCatch({ if (exists("set.seed.worker", envir = .doRedisGlobals$exportenv)) do.call("set.seed.worker", list(0), envir = .doRedisGlobals$exportenv) }, error = function(e) cat(as.character(e), "\n")) eval(.doRedisGlobals$expr, envir = .doRedisGlobals$exportenv)}, error = function(e) e)
16: FUN(X[[i]], ...)
17: lapply(work[[1]]$argsList, .evalWrapper)
18: redisWorker(queue = "jobs", host = "localhost", port = 6379, iter = Inf, linger = 30, log = stdout(), timeout = 2, nodelay = FALSE)
aborting ...
बधाई और stackoverflow पर स्वागत करते हैं। – Tensibai
मुझे लगता है कि आप यहां बहुत चालाक होने की कोशिश कर रहे हैं। मुझे बंद करने का उपयोग करने का कोई कारण नहीं दिख रहा है। आप इस "विस्तार सूची" आवश्यकता क्यों है? जाहिर है, आप जानते हैं कि कैसे बड़े सूचियों होने की जरूरत है, इसलिए उन्हें 'का उपयोग कर वेक्टर (मोड =" सूची ", लंबाई = लंबाई (टेबल्स))' पूर्व आवंटित। – Roland
हाय रोलाण्ड, मैं अपने सुझाव के लिए दो आपत्तियों की है।सबसे पहले, समस्या को स्पष्ट करने के लिए, यह है कि "temp_tot" सभी पृष्ठों (जी-लूप) से सभी तालिकाओं (आई-लूप) की सभी (अंतिम पंक्तियां) एकत्र करता है और प्रत्येक पृष्ठ के लिए तालिकाओं का # ज्ञात नहीं है। मैं देखता हूं कि इसे i-loop (आपके कोड का उपयोग करके) में बनाई गई सूचियों (सी-) (जी-लूप के अंत में) द्वारा हल किया जा सकता है। दूसरी आपत्ति, जिसने मुझे विस्तारित करना पसंद किया .list(), "सी() रास्ता" से उत्पन्न घोंसला वाली संरचना के कारण है (जी-इंडेक्स से विरासत में पहली अनुक्रमणिका, आई-इंडेक्स से दूसरी इकाई) जो कि expanding.list() – dgdi