доступные пакеты по дате публикации - PullRequest
6 голосов
/ 04 января 2012

Можно ли получить дату публикации пакетов CRAN изнутри R? Я хотел бы получить список k самых последних опубликованных пакетов CRAN или, в качестве альтернативы, всех пакетов, опубликованных после даты dd-mm-yy. Похоже на информацию о available_packages_by_date.html ?

Команда available.packages () имеет аргумент «fields», но это только извлекает поля из DESCRIPTION. Поле даты в описании пакета не всегда актуально.

Я могу получить его с помощью умного регулярного выражения со страницы html , но я не уверен, насколько надежным и актуальным является этот HTML-файл ... В какой-то момент Курт может решить дайте макету переделку, которая сломает сценарий. Альтернативой является использование меток времени из CRAN FTP , но я также не уверен, насколько хорошо это решение. Я не уверен, есть ли где-нибудь формально структурированный файл с датами публикации? Я предполагаю, что HTML-страница автоматически генерируется из некоторой БД.

Ответы [ 5 ]

5 голосов
/ 12 января 2012

Оказывается, существует недокументированный файл "packages.rds", который содержит даты публикации (а не время) всех пакетов. Я предполагаю, что эти данные используются для воссоздания HTML-файла каждый день.

Ниже приведена простая функция, извлекающая даты публикации из этого файла:

recent.packages.rds <- function(){
    mytemp <- tempfile();
    download.file("http://cran.r-project.org/web/packages/packages.rds", mytemp);
    mydata <- as.data.frame(readRDS(mytemp), row.names=NA);
    mydata$Published <- as.Date(mydata[["Published"]]);

    #sort and get the fields you like:
    mydata <- mydata[order(mydata$Published),c("Package", "Version", "Published")];
}
3 голосов
/ 06 января 2012

Наилучшим подходом является использование того факта, что пакет DESCRIPTION опубликован на зеркале крана, и поскольку DESCRIPTION взят из пакета сборки, он содержит информацию о том, когда именно он был упакован:

pkgs <- unname(available.packages()[, 1])[1:20]
desc_urls <- paste("http://cran.r-project.org/web/packages/", pkgs, "/DESCRIPTION", sep = "")
desc <- lapply(desc_urls, function(x) read.dcf(url(x)))

sapply(desc, function(x) x[, "Packaged"])
sapply(desc, function(x) x[, "Date/Publication"])

(я ограничиваю первые 20 пакетов здесь, чтобы проиллюстрировать основную идею)

2 голосов
/ 04 января 2012

Здесь функция, которая использует HTML и регулярные выражения.Я все еще предпочитаю получать информацию из более официального места, хотя в случае, если HTML когда-либо меняет макет.

1 голос
/ 05 января 2012

Итак, вот решение, которое использует каталог dir с FTP. Это немного сложно, потому что FTP предоставляет дату в формате linux с отметкой времени или годом. Кроме того, это делает свою работу. Я все еще не уверен, что это надежно, хотя. Если пакеты копируются на другой сервер, все временные карты могут быть сброшены.

recent.packages.ftp <- function(){
    setwd(tempdir())
    download.file("ftp://cran.r-project.org/pub/R/src/contrib/", destfile=tempfile(), method="wget", extra="--no-htmlify");

    #because of --no-htmlify the destfile argument does not work
    datastring <- readLines(".listing");
    unlink(".listing");

    myexpr1 <- "(?<date>[A-Z][a-z]{2} [0-9]{2} [0-9]{2}:[0-9]{2}) (?<name>[a-zA-Z0-9\\.]{2,})_(?<version>[0-9\\.-]*).tar.gz$"
    matches <- gregexpr(myexpr1, datastring, perl=TRUE);
    packagelines <- as.logical(sapply(regmatches(datastring, matches), length));

    #subset proper lines
    matches <- matches[packagelines];
    datastring <- datastring[packagelines];
    N <- length(matches)

    #from the ?regexpr manual       
    parse.one <- function(res, result) {
        m <- do.call(rbind, lapply(seq_along(res), function(i) {
            if(result[i] == -1) return("")
            st <- attr(result, "capture.start")[i, ]
            substring(res[i], st, st + attr(result, "capture.length")[i, ] - 1)
        }))
        colnames(m) <- attr(result, "capture.names")
        m
    }

    #parse all records
    mydf <- data.frame(date=rep(NA, N), name=rep(NA, N), version=rep(NA,N))
    for(i in 1:N){
        mydf[i,] <- parse.one(datastring[i], matches[[i]]);
    }
    row.names(mydf) <- NULL;
    #convert dates
    mydf$date <- strptime(mydf$date, format="%b %d %H:%M");

    #So linux only displays dates for packages of less then six months old. 
    #However strptime will assume the current year for packages that don't have a timestamp
    #Therefore for dates that are in the future, we subtract a year. We can use some margin for timezones. 
    infuture <- (mydf$date > Sys.time() + 31*24*60*60);
    mydf$date[infuture] <- mydf$date[infuture] - 365*24*60*60;

    #sort and return
    mydf <- mydf[order(mydf$date),];
    row.names(mydf) <- NULL;
    return(mydf);
}
0 голосов
/ 05 января 2012

Вы можете обработать страницу http://cran.r-project.org/src/contrib/ и разбить поля по пробелам, чтобы получить полностью указанное имя файла источника пакета, которое включает версию # и суффикс .gz.

В списке есть еще несколько элементов, которые не являются файлами пакетов, например, файлы .rds, различные подкаталоги и т. Д.

За исключением изменений в том, как представлена ​​структура каталогов или расположение файлов, я не могу придумать ничего более авторитетного, чем это.

...