Несколько недель назад я написал скрипт на Python для извлечения некоторых строк из большого (280 МБ) файла CSV . Точнее, я хотел извлечь всю доступную информацию о компаниях в dbpedia, которые имеют поле ISIN. Позже я попробовал то же самое в R, но, как ни старался, скрипт R потребовал в 10 раз больше, чем скрипт python (10 минут против 1 минуты на моем довольно старом ноутбуке). Возможно, это связано с моим знанием R, и в этом случае я буду признателен за подсказку о том, как сделать скрипт быстрее. Вот код питона
from time import clock
clock()
infile = "infobox_de.csv"
outfile = "companies.csv"
reader = open(infile, "rb")
writer = open(outfile, "w")
oldthing = ""
isCompany = False
hasISIN = False
matches = 0
for line in reader:
row = line.strip().split("\t")
if len(row)>0: thing = row[0]
if len(row)>1: key = row[1]
if len(row)>2: value = row[2]
if (len(row)>0) and (oldthing != thing):
if isCompany and hasISIN:
matches += 1
for tup in buf:
writer.write(tup)
buf = []
isCompany = False
hasISIN = False
isCompany = isCompany or ((key.lower()=="wikipageusestemplate") and (value.lower()=="template:infobox_unternehmen"))
hasISIN = hasISIN or ((key.lower()=="isin") and (value!=""))
oldthing = thing
buf.append(line)
writer.close()
print "finished after ", clock(), " seconds; ", matches, " matches."
и вот скрипт R (у меня больше нет эквивалентной версии, но очень похожий, который возвращает фрейм данных вместо записи файла csv и не проверяет ISIN):
infile <- "infobox_de.csv"
maxLines=65000
reader <- file(infile, "r")
writer <- textConnection("queryRes", open = "w", local = TRUE)
writeLines("thing\tkey\tvalue\tetc\n", writer)
oldthing <- ""
hasInfobox <- FALSE
lineNumber <- 0
matches <- 0
key <- ""
thing <- ""
repeat {
lines <- readLines(reader, maxLines)
if (length(lines)==0) break
for (line in lines) {
lineNumber <- lineNumber + 1
row = unlist(strsplit(line, "\t"))
if (length(row)>0) thing <- row[1]
if (length(row)>1) key <- row[2]
if (length(row)>2) value <- row[3]
if ((length(row)>0) && (oldthing != thing)) {
if (hasInfobox) {
matches <- matches + 1
writeLines(buf, writer)
}
buf <- c()
hasInfobox <- FALSE
}
hasInfobox <- hasInfobox || ((tolower(key)=="wikipageusestemplate") && (tolower(value)==tolower("template:infobox_unternehmen")))
oldthing <- thing
buf <- c(buf, line)
}
}
close(reader)
close(writer)
readRes <- textConnection(queryRes, "r")
result <- read.csv(readRes, sep="\t", stringsAsFactors=FALSE)
close(readRes)
result
Что я сделал явно, так это ограничил readLines максимумом до 65000 строк. Я сделал это, потому что думал, что моей машине с 500 МБ ОЗУ не хватит памяти. Я не пробовал без этого ограничения.