diff --git a/NAMESPACE b/NAMESPACE
index 2a238ce..0b9fa26 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -15,6 +15,7 @@ export(spq_arrange)
export(spq_assemble)
export(spq_control_request)
export(spq_count)
+export(spq_endpoint_info)
export(spq_filter)
export(spq_group_by)
export(spq_head)
diff --git a/R/data.R b/R/data.R
index 2ccc8d3..6408f5d 100644
--- a/R/data.R
+++ b/R/data.R
@@ -21,7 +21,7 @@ wikidata_url <- function() {
#' \describe{
#' \item{name}{the abbreviated name of the SPARQL endpoint}
#' \item{url}{the full address of the SPARQL endpoint}
-#' ...
+#' \item{label_property}{the property used for labelling}
#' }
"usual_endpoints"
diff --git a/R/glitter-package.R b/R/glitter-package.R
index f7d4732..900c17b 100644
--- a/R/glitter-package.R
+++ b/R/glitter-package.R
@@ -8,3 +8,7 @@
#' @importFrom lifecycle deprecated
## usethis namespace: end
NULL
+
+release_bullets <- function() {
+ c("Update articles cf data-raw/articles.R")
+}
diff --git a/R/spq_endpoint_info.R b/R/spq_endpoint_info.R
new file mode 100644
index 0000000..6475c21
--- /dev/null
+++ b/R/spq_endpoint_info.R
@@ -0,0 +1,23 @@
+#' Create the endpoint info object for `spq_init()`
+#'
+#' @param label_property Property used by the endpoint for labelling.
+#'
+#' @return A list to be used in `spq_init()`'s `endpoint_info` argument.
+#' @export
+#'
+#' @examples
+#' spq_endpoint_info(label_property = "skos:preflabel")
+spq_endpoint_info <- function(label_property = "rdfs:prefLabel") {
+
+ # TODO check property more
+ if (!is.character(label_property)) {
+ cli::cli_abort("Must provide a character as {.arg label_property}.")
+ }
+
+ structure(
+ list(
+ label_property = label_property
+ ),
+ class = "glitter_endpoint_info"
+ )
+}
diff --git a/R/spq_init.R b/R/spq_init.R
index d3efccf..ed21aad 100644
--- a/R/spq_init.R
+++ b/R/spq_init.R
@@ -2,6 +2,9 @@
#'
#' @param endpoint Endpoint, either name if it is in `usual_endpoints`,
#' or an URL
+#' @param endpoint_info Do not use for an usual endpoint in `usual_endpoints`!
+#' Information about
+#' the endpoint
#' @param request_control An object as returned by [`spq_control_request()`]
#'
#' @return A query object
@@ -28,22 +31,35 @@ spq_init = function(
max_seconds = getOption("glitter.max_seconds", 120L),
timeout = getOption("glitter.timeout", 1000L),
request_type = c("url", "body-form")
+ ),
+ endpoint_info = spq_endpoint_info(
+ label_property = "rdfs:label"
)
) {
if (!inherits(request_control, "glitter_request_control")) {
cli::cli_abort("{.arg request_control} must be created by {.fun spq_control_request}.")
+ }
+ if (!inherits(endpoint_info, "glitter_endpoint_info")) {
+ cli::cli_abort("{.arg endpoint_info} must be created by {.fun spq_endpoint_info}.")
}
# if endpoint passed as name, get url
endpoint = tolower(endpoint)
usual_endpoint_info = usual_endpoints %>%
dplyr::filter(.data$name == endpoint)
- endpoint = if (nrow(usual_endpoint_info) > 0) {
- dplyr::pull(usual_endpoint_info, .data$url)
+ if (nrow(usual_endpoint_info) > 0) {
+ endpoint = dplyr::pull(usual_endpoint_info, .data$url)
+ label_property = dplyr::pull(usual_endpoint_info, .data$label_property)
} else {
endpoint
+ label_property = NULL
}
+ endpoint_info = list(
+ endpoint_url = endpoint,
+ label_property = label_property %||% endpoint_info[["label_property"]]
+ )
+
query = list(
prefixes_provided = tibble::tibble(name = NULL, url = NULL),
prefixes_used = NULL,
@@ -56,7 +72,7 @@ spq_init = function(
group_by = NULL,
order_by = NULL,
offset = NULL,
- endpoint = endpoint,
+ endpoint_info = endpoint_info,
request_control = request_control
)
diff --git a/R/spq_label.R b/R/spq_label.R
index 1142983..9377a4a 100644
--- a/R/spq_label.R
+++ b/R/spq_label.R
@@ -12,6 +12,12 @@
#' `spq_select(blop, .overwrite = TRUE)` means you get the label as `blop`,
#' the "original" blop variable isn't returned.
#'
+#' @details
+#' `spq_label()` uses the property:
+#' - associated with the usual endpoint see `usual_endpoints`
+#' - the property indicated in [`spq_endpoint_info()`]
+#'
+#'
#' @return A query object
#' @export
#'
@@ -35,6 +41,10 @@ spq_label <- function(.query,
.required = FALSE,
.languages = getOption("glitter.lang", "en$"),
.overwrite = FALSE) {
+
+ label_property <- .query[["endpoint_info"]][["label_property"]] %||%
+ "rdfs:label"
+
vars = purrr::map_chr(rlang::enquos(...), spq_treat_argument)
if (!is.null(.languages)) .languages = tolower(.languages)
@@ -43,7 +53,7 @@ spq_label <- function(.query,
vars,
function(query, x) {
if (is.null(.languages)) {
- filter = NA
+ filter = NULL
} else {
languages_filter <- purrr::map_chr(.languages, create_lang_filter, x = x)
@@ -56,14 +66,17 @@ spq_label <- function(.query,
if (.required) {
q = spq_add(
query,
- sprintf("%s rdfs:label %s_labell", x, x),
+ sprintf("%s %s %s_labell", x, label_property, x),
.required = .required
)
- q = spq_filter(q, spq(filter))
+ if (!is.null(filter)) {
+ q = spq_filter(q, spq(filter))
+ }
+
} else {
q = spq_add(
query,
- sprintf("%s rdfs:label %s_labell", x, x),
+ sprintf("%s %s %s_labell", x,label_property, x),
.required = .required,
.filter = filter
)
diff --git a/R/spq_language.R b/R/spq_language.R
index c8664c4..d84d865 100644
--- a/R/spq_language.R
+++ b/R/spq_language.R
@@ -3,8 +3,8 @@
#' @param language the language in which the labels will be provided (defaults to "en" for English). See complete list of Wikimedia language codes [here](https://www.wikidata.org/wiki/Help:Wikimedia_language_codes/lists/all). You can also set language to "auto" and then the Wikidata SPARQL engine will try and detect your language automatically. Specifying several languages will return labels with languages following the priority specified (e.g. with language="fr,en", the label will be returned preferentially in French, or, if there is not French label for the item, in English).
#' @return A query object
#' @export
-#' @examples
#' @keywords internal
+#' @examples
#' spq_init() %>%
#' spq_add("?film wdt:P31 wd:Q11424") %>%
#' spq_label(film, .languages = c("fr$", "en$")) %>%
diff --git a/R/spq_perform.R b/R/spq_perform.R
index f908993..4180610 100644
--- a/R/spq_perform.R
+++ b/R/spq_perform.R
@@ -50,7 +50,7 @@ spq_perform = function(.query,
"spq_init(endpoint)"
)
} else {
- endpoint = .query[["endpoint"]]
+ endpoint = .query[["endpoint_info"]][["endpoint_url"]]
}
diff --git a/R/spq_rename_var.R b/R/spq_rename_var.R
index d55aa35..eb315e7 100644
--- a/R/spq_rename_var.R
+++ b/R/spq_rename_var.R
@@ -5,7 +5,7 @@ spq_rename_var <- function(.query, old, new) {
}
if (question_mark(new) %in% .query[["vars"]][["name"]]) {
- if (.query[["vars"]][["renamed"]][.query[["vars"]][["name"]] == question_mark(new)]) {
+ if (any(.query[["vars"]][["renamed"]][.query[["vars"]][["name"]] == question_mark(new)])) {
.query = spq_rename_var(.query, new, sprintf("%s0", new))
} else {
cli::cli_abort("Can't rename {.field {old}} to {.field {new}} as {.field {new}} already exists.")
diff --git a/data-raw/articles.R b/data-raw/articles.R
new file mode 100644
index 0000000..7beb35b
--- /dev/null
+++ b/data-raw/articles.R
@@ -0,0 +1,3 @@
+withr::with_dir("vignettes/articles", {
+ knitr::knit("glitter_bibliometry.Rmd.orig", output = "glitter_bibliometry.Rmd")
+})
diff --git a/data-raw/create_usual_endpoints.R b/data-raw/create_usual_endpoints.R
index 6018b75..4580acf 100644
--- a/data-raw/create_usual_endpoints.R
+++ b/data-raw/create_usual_endpoints.R
@@ -1,14 +1,2 @@
-endpoints=tibble::tibble(name=c("wikidata",
- "dbpedia",
- "databnf",
- "isidore",
- "hal",
- "symogih"),
- url=c("https://query.wikidata.org/",
- "https://dbpedia.org/sparql",
- "https://data.bnf.fr/sparql",
- "https://isidore.science/sparql",
- "http://sparql.archives-ouvertes.fr/sparql",
- "http://bhp-publi.ish-lyon.cnrs.fr:8888/sparql"))
usual_endpoints=readr::read_csv("data-raw/usual_endpoints.csv")
usethis::use_data(usual_endpoints,overwrite=TRUE)
diff --git a/data-raw/usual_endpoints.csv b/data-raw/usual_endpoints.csv
index ef0fddc..ed4412f 100644
--- a/data-raw/usual_endpoints.csv
+++ b/data-raw/usual_endpoints.csv
@@ -1,6 +1,6 @@
-name,url
-wikidata,https://query.wikidata.org/sparql
-dbpedia,https://dbpedia.org/sparql
-databnf,https://data.bnf.fr/sparql
-isidore,https://isidore.science/sparql
-hal,http://sparql.archives-ouvertes.fr/sparql
+name,url,label_property
+wikidata,https://query.wikidata.org/sparql,rdfs:label
+dbpedia,https://dbpedia.org/sparql,rdfs:label
+databnf,https://data.bnf.fr/sparql,rdfs:label
+isidore,https://isidore.science/sparql,rdfs:label
+hal,http://sparql.archives-ouvertes.fr/sparql,skos:prefLabel
diff --git a/data/usual_endpoints.rda b/data/usual_endpoints.rda
index 612019b..2f6a672 100644
Binary files a/data/usual_endpoints.rda and b/data/usual_endpoints.rda differ
diff --git a/man/spq_endpoint_info.Rd b/man/spq_endpoint_info.Rd
new file mode 100644
index 0000000..262f8f2
--- /dev/null
+++ b/man/spq_endpoint_info.Rd
@@ -0,0 +1,20 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/spq_endpoint_info.R
+\name{spq_endpoint_info}
+\alias{spq_endpoint_info}
+\title{Create the endpoint info object for \code{spq_init()}}
+\usage{
+spq_endpoint_info(label_property = "rdfs:prefLabel")
+}
+\arguments{
+\item{label_property}{Property used by the endpoint for labelling.}
+}
+\value{
+A list to be used in \code{spq_init()}'s \code{endpoint_info} argument.
+}
+\description{
+Create the endpoint info object for \code{spq_init()}
+}
+\examples{
+spq_endpoint_info(label_property = "skos:preflabel")
+}
diff --git a/man/spq_init.Rd b/man/spq_init.Rd
index f087084..5c5becc 100644
--- a/man/spq_init.Rd
+++ b/man/spq_init.Rd
@@ -10,7 +10,8 @@ spq_init(
"glitter R package (https://github.com/lvaudor/glitter)"), max_tries =
getOption("glitter.max_tries", 3L), max_seconds = getOption("glitter.max_seconds",
120L), timeout = getOption("glitter.timeout", 1000L), request_type = c("url",
- "body-form"))
+ "body-form")),
+ endpoint_info = spq_endpoint_info(label_property = "rdfs:label")
)
}
\arguments{
@@ -18,6 +19,10 @@ spq_init(
or an URL}
\item{request_control}{An object as returned by \code{\link[=spq_control_request]{spq_control_request()}}}
+
+\item{endpoint_info}{Do not use for an usual endpoint in \code{usual_endpoints}!
+Information about
+the endpoint}
}
\value{
A query object
diff --git a/man/spq_label.Rd b/man/spq_label.Rd
index 7ab98a4..f17da35 100644
--- a/man/spq_label.Rd
+++ b/man/spq_label.Rd
@@ -38,6 +38,13 @@ A query object
\description{
Label variables
}
+\details{
+\code{spq_label()} uses the property:
+\itemize{
+\item associated with the usual endpoint see \code{usual_endpoints}
+\item the property indicated in \code{\link[=spq_endpoint_info]{spq_endpoint_info()}}
+}
+}
\section{Example}{
diff --git a/man/spq_language.Rd b/man/spq_language.Rd
index b563a5d..f9ba949 100644
--- a/man/spq_language.Rd
+++ b/man/spq_language.Rd
@@ -23,3 +23,4 @@ spq_init() \%>\%
spq_label(film, .languages = c("fr$", "en$")) \%>\%
spq_head(10)
}
+\keyword{internal}
diff --git a/man/usual_endpoints.Rd b/man/usual_endpoints.Rd
index 5d21f24..c05f41d 100644
--- a/man/usual_endpoints.Rd
+++ b/man/usual_endpoints.Rd
@@ -9,7 +9,7 @@ A data frame with usual SPARQL endpoints and abbreviated names
\describe{
\item{name}{the abbreviated name of the SPARQL endpoint}
\item{url}{the full address of the SPARQL endpoint}
-...
+\item{label_property}{the property used for labelling}
}
}
\usage{
diff --git a/tests/testthat/_snaps/spq_label.md b/tests/testthat/_snaps/spq_label.md
index a893c01..f3ddf49 100644
--- a/tests/testthat/_snaps/spq_label.md
+++ b/tests/testthat/_snaps/spq_label.md
@@ -60,6 +60,30 @@
}
+# spq_label() for not rdfs:label
+
+ Code
+ spq_init(endpoint = "hal") %>% spq_add(
+ "haldoc:inria-00362381 dcterms:hasVersion ?version") %>% spq_add(
+ "?version dcterms:type ?type") %>% spq_label(type)
+ Output
+ PREFIX dcterms:
+ PREFIX skos:
+ PREFIX haldoc:
+ SELECT ?type (COALESCE(?type_labell,'') AS ?type_label) ?version
+ WHERE {
+
+ haldoc:inria-00362381 dcterms:hasVersion ?version.
+ ?version dcterms:type ?type.
+ OPTIONAL {
+ ?type skos:prefLabel ?type_labell.
+ FILTER(lang(?type_labell) IN ('en'))
+ }
+
+
+ }
+
+
# spq_label() .overwrite
Code
@@ -91,3 +115,22 @@
}
+# spq_label() .languages = NULL
+
+ Code
+ spq_init(endpoint = "hal") %>% spq_label(labo, .languages = NULL, .required = TRUE) %>%
+ spq_add("?labo dcterms:identifier ?labo_id", .required = FALSE) %>%
+ spq_filter(str_detect(labo_label, "EVS|(UMR 5600)|(Environnement Ville Soc)"))
+ Output
+ PREFIX dcterms:
+ PREFIX skos:
+ SELECT ?labo (COALESCE(?labo_labell,'') AS ?labo_label) ?labo_id
+ WHERE {
+
+ ?labo skos:prefLabel ?labo_labell.
+ OPTIONAL {?labo dcterms:identifier ?labo_id.}
+ BIND(COALESCE(?labo_labell,'') AS ?labo_label)
+ FILTER(REGEX(?labo_label,"EVS|(UMR 5600)|(Environnement Ville Soc)"))
+ }
+
+
diff --git a/tests/testthat/test-spq_label.R b/tests/testthat/test-spq_label.R
index 8a2758a..fc7803e 100644
--- a/tests/testthat/test-spq_label.R
+++ b/tests/testthat/test-spq_label.R
@@ -35,6 +35,15 @@ test_that("spq_label() works", {
)
})
+test_that("spq_label() for not rdfs:label", {
+ expect_snapshot(
+ spq_init(endpoint = "hal") %>%
+ spq_add("haldoc:inria-00362381 dcterms:hasVersion ?version") %>%
+ spq_add("?version dcterms:type ?type") %>%
+ spq_label(type)
+ )
+})
+
test_that("spq_label() .overwrite", {
expect_snapshot(
@@ -47,3 +56,12 @@ test_that("spq_label() .overwrite", {
spq_label(mayor, place, .languages = "en$", .overwrite = TRUE)
)
})
+
+test_that("spq_label() .languages = NULL", {
+ expect_snapshot(
+ spq_init(endpoint = "hal") %>%
+ spq_label(labo, .languages = NULL, .required = TRUE) %>%
+ spq_add("?labo dcterms:identifier ?labo_id", .required = FALSE) %>%
+ spq_filter(str_detect(labo_label,"EVS|(UMR 5600)|(Environnement Ville Soc)"))
+ )
+})
diff --git a/vignettes/articles/figure/docs_LV_recents-1.png b/vignettes/articles/figure/docs_LV_recents-1.png
new file mode 100644
index 0000000..b0d8fe1
Binary files /dev/null and b/vignettes/articles/figure/docs_LV_recents-1.png differ
diff --git a/vignettes/articles/figure/interet_LV-1.png b/vignettes/articles/figure/interet_LV-1.png
new file mode 100644
index 0000000..94659ac
Binary files /dev/null and b/vignettes/articles/figure/interet_LV-1.png differ
diff --git a/vignettes/articles/figure/interet_LV_run-1.png b/vignettes/articles/figure/interet_LV_run-1.png
new file mode 100644
index 0000000..47cb32a
Binary files /dev/null and b/vignettes/articles/figure/interet_LV_run-1.png differ
diff --git a/vignettes/articles/figure/labo_EVS_filter-1.png b/vignettes/articles/figure/labo_EVS_filter-1.png
new file mode 100644
index 0000000..ba26a8e
Binary files /dev/null and b/vignettes/articles/figure/labo_EVS_filter-1.png differ
diff --git a/vignettes/articles/figure/orga_LV_prep-1.png b/vignettes/articles/figure/orga_LV_prep-1.png
new file mode 100644
index 0000000..b528fda
Binary files /dev/null and b/vignettes/articles/figure/orga_LV_prep-1.png differ
diff --git a/vignettes/articles/figure/orga_LV_run-1.png b/vignettes/articles/figure/orga_LV_run-1.png
new file mode 100644
index 0000000..f0524f0
Binary files /dev/null and b/vignettes/articles/figure/orga_LV_run-1.png differ
diff --git a/vignettes/articles/figure/test_LV-1.png b/vignettes/articles/figure/test_LV-1.png
new file mode 100644
index 0000000..b3a1a16
Binary files /dev/null and b/vignettes/articles/figure/test_LV-1.png differ
diff --git a/vignettes/articles/glitter_bibliometry.Rmd b/vignettes/articles/glitter_bibliometry.Rmd
index 8727f63..9343de0 100644
--- a/vignettes/articles/glitter_bibliometry.Rmd
+++ b/vignettes/articles/glitter_bibliometry.Rmd
@@ -8,9 +8,7 @@ vignette: >
%\VignetteEncoding{UTF-8}
---
-```{r setup, include=FALSE}
-knitr::opts_chunk$set(echo = TRUE)
-```
+
This article deals with queries on the [HAL](https://hal.science/) (for "Hyper Article en Ligne") triplestore, [dataHAL](https://data.hal.science/). **HAL** is the **bibliograpic open archive** chosen by French research institutions, universities, and grandes écoles. Hence, we suppose this article will only be useful to French-speaking R users and will provide it **in French** from now on...
@@ -20,7 +18,8 @@ On peut ainsi imaginer utiliser ces données pour **générer automatiquement et
Dans la suite de cet article je montrerai comment explorer et exploiter ces données à l'aide de R, et (notamment) du paquet glitter (pour créer et réaliser les requêtes) et du paquet [sequins](https://lvaudor.github.io/sequins/) (pour visualiser les requêtes).
-```{r libs, message=FALSE}
+
+```r
library(glitter)
library(sequins)
library(dplyr)
@@ -28,41 +27,61 @@ library(tidyr)
library(ggplot2)
```
+# Requête de base
+
+Afin de ne pas trop en demander à HAL, créons une requête de base qui n'envoient pas trop de requêtes d'un coup.
+
+
+```r
+hal_basic_request <- spq_init(
+ "hal",
+ request_control = spq_control_request(rate = 3/60)
+)
+```
+
# Entrée par auteur·rice
Essayons par exemple d'examiner s'il existe dans la base quelqu'un qui s'appelle (tout à fait au hasard) "Lise Vaudor":
-```{r test_LV}
-test_LV=spq_init("hal") %>%
+
+```r
+test_LV = hal_basic_request %>%
spq_add("?personne foaf:name 'Lise Vaudor'") %>% # récupère les personnes appelées "Lise Vaudor"
spq_perform()
DT::datatable(test_LV)
```
-Il existe bien une personne ayant ce nom dans la base de données, qui fait l'objet d'une [fiche consultable](`r test_LV$personne[1]`).
+![plot of chunk test_LV](figure/test_LV-1.png)
+
+Il existe bien une personne ayant ce nom dans la base de données, qui fait l'objet d'une [fiche consultable](https://data.archives-ouvertes.fr/author/299).
La consultation de cette page montre que deux propriétés sont souvent renseignées: **foaf:interest** et **foaf:topic_interest**. Cette dernière propriété semble regrouper des mots-clés issus de l'ensemble des publications de l'auteur alors que foaf:interest correspond à des centres d'intérêt déclarés (probablement lors de la création du profil HAL: à vrai dire je ne m'en souviens plus!).
Quoi qu'il en soit, l'information relative aux centres d'intérêt est accessible comme suit:
-```{r interet_LV, fig.width=7,fig.height=7}
-requete = spq_init("hal") %>%
+
+```r
+requete = hal_basic_request %>%
spq_add("?personne foaf:name 'Lise Vaudor'") %>%
spq_add("?personne foaf:interest ?interet") %>% # récupère les centres d'intérêt
- spq_add("?interet skos:prefLabel ?interet_label") %>% # étiquette les centres d'intérêt
- spq_filter(lang(interet_label) == 'fr')
+ spq_label(interet, .languages = "fr") # étiquette les centres d'intérêt
sequins::graph_query(requete, layout = "tree")
```
+![plot of chunk interet_LV](figure/interet_LV-1.png)
+
+
-```{r interet_LV_run}
+```r
interet_LV = requete %>% # garde seulement les étiquettes en français
spq_perform()
DT::datatable(interet_LV)
```
+![plot of chunk interet_LV_run](figure/interet_LV_run-1.png)
+
# Documents d'un·e auteur·rice
Une des petites subtilités du modèle de données HAL consiste à considérer que **un document a un créateur·rice -- ou auteur·rice -- et un·e créateur·rice correspond à une personne**.
@@ -74,43 +93,71 @@ Par exemple, l'article "How sampling influences the statistical power to detect
Ainsi, c'est en considérant les créateurs de documents que l'on va récupérer les affiliations: **l'affiliation est une information qui se récupère en adoptant une entrée par document plutôt que par auteur·rice**.
-```{r orga_LV_prep, fig.width=7, fig.height=8}
-requete = spq_init("hal") %>%
+
+```r
+requete = hal_basic_request %>%
spq_add("?doc dcterms:creator ?createur") %>% # documents crées par créateur
- spq_add("?createur hal:structure ?affil") %>% # créateur correspond à une affiliation
+ spq_add("?createur hal:structure ?affiliation") %>% # créateur correspond à une affiliation
spq_add("?createur hal:person ?personne") %>% # créateur correspond à une personne
- spq_add("?personne foaf:name 'Lise Vaudor'") %>%
- spq_add("?affil skos:prefLabel ?affiliation") %>% # étiquette affiliation
+ spq_add("?personne foaf:name 'Lise Vaudor'") %>%
+ spq_label(affiliation, .overwrite = TRUE, .languages = NULL) %>% # étiquette affiliation
spq_group_by(affiliation) %>% # groupe par affiliation
- spq_summarise(n = n()) %>%
+ spq_summarise(n = n()) %>%
spq_arrange(desc(n))
requete
+```
+```
+## PREFIX foaf:
+## PREFIX dcterms:
+## PREFIX skos:
+## PREFIX hal:
+## SELECT ?affiliation (COUNT(*) AS ?n)
+## WHERE {
+##
+## ?doc dcterms:creator ?createur.
+## ?createur hal:structure ?affiliation0.
+## ?createur hal:person ?personne.
+## ?personne foaf:name 'Lise Vaudor'.
+## OPTIONAL {?affiliation0 skos:prefLabel ?affiliation_labell.}
+## BIND(COALESCE(?affiliation_labell,'') AS ?affiliation)
+##
+## }
+## GROUP BY ?affiliation
+## ORDER BY DESC(?n)
+```
+
+```r
sequins::graph_query(requete, layout="tree")
```
-```{r orga_LV_run}
+![plot of chunk orga_LV_prep](figure/orga_LV_prep-1.png)
+
+
+```r
orga_LV = requete %>% # renvoie le nombre d'enregistrements
spq_perform()
-DT::datatable(orga_LV)
+DT::datatable(orga_LV)
```
-## Documents
+![plot of chunk orga_LV_run](figure/orga_LV_run-1.png)
+
+## Documents
Si l'on ne s'intéresse pas aux affiliations mais aux **documents** eux-mêmes:
-```{r docs_LV}
-docs_LV = spq_init(endpoint = "hal") %>%
+
+```r
+docs_LV = hal_basic_request %>%
spq_add("?doc dcterms:creator ?createur") %>%
- spq_add("?createur hal:structure ?affil") %>%
+ spq_add("?createur hal:structure ?affiliation") %>%
spq_add("?createur hal:person ?personne") %>%
spq_add("?personne foaf:name 'Lise Vaudor'") %>%
- spq_add("?affil skos:prefLabel ?affiliation") %>%
- spq_add("?doc dcterms:type ?type") %>%
- spq_add("?type skos:prefLabel ?type_label") %>%
- spq_filter(lang(type_label) == 'fr') %>%
+ spq_label(affiliation, .overwrite = TRUE, .languages = NULL) %>%
+ spq_add("?doc dcterms:type ?type") %>%
+ spq_label(type, .languages = "fr") %>%
spq_add("?doc dcterms:bibliographicCitation ?citation") %>%
spq_add("?doc dcterms:issued ?date") %>%
spq_mutate(date = str_sub(as.character(date), 1, 4)) %>%
@@ -121,15 +168,35 @@ docs_LV = spq_init(endpoint = "hal") %>%
docs_LV
```
-Cette requête renvoie une table comptant `r nrow(docs_LV)`. Voici les 20 documents les plus récents:
+```
+## # A tibble: 106 × 4
+## citation date type_label affiliation
+##
+## 1 "Lise Vaudor, E. Parrot, Hervé Piégay. Describi… 2013 Poster de… Plateforme…
+## 2 "Lise Vaudor, Sébastien Rey-Coyrehourcq, Fabien… 2018 Note de l… Environnem…
+## 3 "Lise Vaudor, Hervé Piégay, Vincent Wawrzyniak,… 2016 Communica… Environnem…
+## 4 "Véronique Benacchio, Hervé Piégay, Thomas Buff… 2017 Article d… Environnem…
+## 5 "V. Benacchio, Hervé Piégay, Thomas Buffin-Bela… 2014 Communica… Environnem…
+## 6 "Thomas Buhler, Emeline Comby, Lise Vaudor, Thi… 2021 Article d… Environnem…
+## 7 "Matthieu Adam, Marylise Cottet, Sylvie Morarde… 2020 Article d… Environnem…
+## 8 "Bastien Bonef, Lionel Gérard, Jean-Luc Rouvièr… 2015 Article d… Nanophysiq…
+## 9 "Hervé Piégay, Fanny Arnaud, Cassel Mathieu, Th… 2016 Article d… Environnem…
+## 10 "Jérémie Riquier, Hervé Piégay, Nicolas Lamouro… 2016 Communica… Environnem…
+## # ℹ 96 more rows
+```
+
+Cette requête renvoie une table comptant 106. Voici les 20 documents les plus récents:
-```{r docs_LV_recents}
+
+```r
docs_LV %>%
arrange(desc(date)) %>%
- head(20) %>%
- DT::datatable()
+ head(20) %>%
+ DT::datatable()
```
+![plot of chunk docs_LV_recents](figure/docs_LV_recents-1.png)
+
# Entrée par laboratoire
@@ -140,44 +207,65 @@ Intéressons-nous maintenant aux **publications issues d'un laboratoire**. Ici,
Essayons de le retrouver dans la base de données:
-```{r labo_EVS}
-labo_EVS = spq_init(endpoint = "hal") %>%
- spq_add("?labo skos:prefLabel ?labo_label") %>%
- spq_add("?labo dcterms:identifier ?labo_id", .required = FALSE) %>%
+
+```r
+labo_EVS = hal_basic_request %>%
+ spq_label(labo, .languages = NULL, .required = TRUE) %>%
+ spq_add("?labo dcterms:identifier ?labo_id", .required = FALSE) %>%
spq_filter(str_detect(labo_label,"EVS|(UMR 5600)|(Environnement Ville Soc)")) %>%
spq_perform()
labo_EVS
```
+```
+## # A tibble: 21 × 3
+## labo labo_label labo_id
+##
+## 1 https://data.archives-ouvertes.fr/revue/36364 REVSTAT - Statist…
+## 2 https://data.archives-ouvertes.fr/revue/115361 Issue 4 of SCS Tr…
+## 3 https://data.archives-ouvertes.fr/structure/54063 GEVSM
+## 4 https://data.archives-ouvertes.fr/structure/145345 Environnement Vil… UMR5600
+## 5 https://data.archives-ouvertes.fr/structure/390864 UMR 5600 EVS
+## 6 https://data.archives-ouvertes.fr/structure/458855 Plateforme ISIG. …
+## 7 https://data.archives-ouvertes.fr/structure/493368 Environnement Vil…
+## 8 https://data.archives-ouvertes.fr/structure/516259 UMR CNRS 5600 EVS…
+## 9 https://data.archives-ouvertes.fr/structure/516301 Environnement Vil…
+## 10 https://data.archives-ouvertes.fr/structure/520344 EVS-LAURE UMR 56…
+## # ℹ 11 more rows
+```
+
Bon! Eh bien, étant donné la diversité des formats dans la dénomination d'EVS, un petit tri manuel s'impose.
-```{r labo_EVS_filter}
-labo_EVS = labo_EVS %>%
- unique() %>%
- mutate(num = 1:n()) %>%
+
+```r
+labo_EVS = labo_EVS %>%
+ unique() %>%
+ mutate(num = 1:n()) %>%
filter(!(num %in% c(1,2,3,18))) %>% # ici je retire les labos qui ne correspondent pas à UMR 5600 / EVS
select(-num)
DT::datatable(labo_EVS)
```
+![plot of chunk labo_EVS_filter](figure/labo_EVS_filter-1.png)
+
Créons maintenant une fonction qui permet de récupérer l'**ensemble des documents pour chacune de ces dénominations de laboratoire**.
-```{r get_docs_lab}
+
+```r
get_docs_lab = function(lab){
+ Sys.sleep(30) # extra-safe
lab = paste0("<",lab,">")
- result = spq_init(endpoint = "hal") %>%
- spq_add(glue::glue("?createur hal:structure {lab}")) %>%
+ result = hal_basic_request %>%
+ spq_add(glue::glue("?createur hal:structure {lab}")) %>%
spq_add("?createur hal:person ?personne") %>%
spq_add("?personne foaf:name ?auteur") %>%
- spq_add("?doc dcterms:creator ?createur") %>%
+ spq_add("?doc dcterms:creator ?createur") %>%
spq_select(-createur) %>%
- spq_add("?doc dcterms:type ?type") %>% # récupère le type de document
- spq_add("?type skos:prefLabel ?type_label") %>% # étiquette le type de document
- spq_filter(lang(type_label) == 'fr') %>% # ... en français
+ spq_label(type, .languages = "fr") %>% # étiquette le type de document en français
spq_add("?doc dcterms:bibliographicCitation ?citation") %>% # récupère la citation
spq_add("?doc dcterms:issued ?date") %>%
spq_perform() %>%
- mutate(date = stringr::str_sub(date,1,4)) %>%
+ mutate(date = stringr::str_sub(date,1,4)) %>%
select(auteur, type = type_label, date, citation)
return(result)
}
@@ -185,51 +273,97 @@ get_docs_lab = function(lab){
Appliquons maintenant cette fonction à chacune des dénominations possibles pour le labo EVS:
-```{r apply_get_docs_lab}
-docs_EVS = labo_EVS %>%
+
+```r
+docs_EVS = labo_EVS %>%
group_by(labo, labo_label) %>%
- tidyr::nest() %>%
- mutate(data = purrr::map(labo, get_docs_lab)) %>%
- tidyr::unnest(cols="data")
+ tidyr::nest() %>%
+ mutate(data = purrr::map(labo, get_docs_lab)) %>%
+ tidyr::unnest(cols="data")
+```
+
+```
+## Error in `mutate()`:
+## ℹ In argument: `data = purrr::map(labo, get_docs_lab)`.
+## ℹ In group 8: `labo = "https://data.archives-ouvertes.fr/structure/145345"`,
+## `labo_label = "Environnement Ville Société"`.
+## Caused by error in `purrr::map()`:
+## ℹ In index: 1.
+## Caused by error in `httr2::req_perform()` at glitter/R/send_sparql.R:113:3:
+## ! HTTP 500 Internal Server Error.
+```
+```r
dim(docs_EVS)
```
-Cette table compte de nombreux enregistrements (`r nrow(docs_EVS)`). On montre ci-dessous les plus récents (à partir de 2020):
+```
+## Error in eval(expr, envir, enclos): object 'docs_EVS' not found
+```
+
+Cette table compte de nombreux enregistrements. On montre ci-dessous les plus récents (à partir de 2020):
+
-```{r docs_EVS_show}
-docs_EVS_show = docs_EVS %>%
+```r
+docs_EVS_show = docs_EVS %>%
select(-labo) %>%
- filter(date >= 2020) %>%
- unique() %>%
- select(auteur, date, type, citation, citation) %>%
+ filter(date >= 2020) %>%
+ unique() %>%
+ select(auteur, date, type, citation, citation) %>%
ungroup()
-
-dim(docs_EVS_show)
+```
+
+```
+## Error in select(., -labo): object 'docs_EVS' not found
+```
-DT::datatable(docs_EVS_show)
+```r
+dim(docs_EVS_show)
+```
+
+```
+## Error in eval(expr, envir, enclos): object 'docs_EVS_show' not found
+```
+
+```r
+DT::datatable(docs_EVS_show)
+```
+
+```
+## Error in crosstalk::is.SharedData(data): object 'docs_EVS_show' not found
```
# Rendus graphiques
On peut dès lors utiliser ces données pour produire un **certain nombre de graphiques** permettant d'apprécier la production du laboratoire au cours du temps:
-```{r plot_datecitation}
+
+```r
docs_datecitation = docs_EVS %>%
- group_by(type) %>%
- mutate(ntype = n()) %>%
- ungroup() %>%
+ group_by(type) %>%
+ mutate(ntype = n()) %>%
+ ungroup() %>%
mutate(ntot = n()) %>%
- mutate(proptype = ntype/ntot) %>%
- filter(proptype > 0.05) %>%
+ mutate(proptype = ntype/ntot) %>%
+ filter(proptype > 0.05) %>%
group_by(date, citation, type) %>%
- summarise(n = n()) %>%
+ summarise(n = n()) %>%
filter(date > 2015)
+```
+
+```
+## Error in group_by(., type): object 'docs_EVS' not found
+```
+```r
ggplot(docs_datecitation, aes(x = date, y = n, fill = type)) +
geom_bar(stat = "identity") +
facet_grid(rows = vars(type))
```
+```
+## Error in ggplot(docs_datecitation, aes(x = date, y = n, fill = type)): object 'docs_datecitation' not found
+```
+
Il ne s'agit là que d'un exemple (parmi beaucoup d'autres possibilités comme l'exploitation de mots clés, de statistiques par journal, de réseaux d'auteurs) pour exploiter ces données. Nanmoins ces méthodes allant au-delà du "scope" du package glitter nous n'irons pas plus loin en terme d'analyse des résultats des requêtes dans ce document.
diff --git a/vignettes/articles/glitter_bibliometry.Rmd.orig b/vignettes/articles/glitter_bibliometry.Rmd.orig
new file mode 100644
index 0000000..008951c
--- /dev/null
+++ b/vignettes/articles/glitter_bibliometry.Rmd.orig
@@ -0,0 +1,244 @@
+---
+title: "glitter for HAL (en français)"
+author: "Lise Vaudor"
+output: rmarkdown::html_vignette
+vignette: >
+ %\VignetteIndexEntry{glitter for HAL}
+ %\VignetteEngine{knitr::rmarkdown}
+ %\VignetteEncoding{UTF-8}
+---
+
+```{r setup, include=FALSE}
+knitr::opts_chunk$set(echo = TRUE, message = FALSE)
+```
+
+This article deals with queries on the [HAL](https://hal.science/) (for "Hyper Article en Ligne") triplestore, [dataHAL](https://data.hal.science/). **HAL** is the **bibliograpic open archive** chosen by French research institutions, universities, and grandes écoles. Hence, we suppose this article will only be useful to French-speaking R users and will provide it **in French** from now on...
+
+Les données contenues dans le triplestore HAL sont a priori utilisables pour générer des **rapports bibliographiques** pour une **personne**, une **organisation** (UMR par exemple), en triant par exemple par **année** ou par **période**.
+
+On peut ainsi imaginer utiliser ces données pour **générer automatiquement et de manière reproductible** un certain nombre de **tables ou graphiques** en lien avec les **évaluations** du personnel publiant des établissements de recherche.
+
+Dans la suite de cet article je montrerai comment explorer et exploiter ces données à l'aide de R, et (notamment) du paquet glitter (pour créer et réaliser les requêtes) et du paquet [sequins](https://lvaudor.github.io/sequins/) (pour visualiser les requêtes).
+
+```{r libs, message=FALSE}
+library(glitter)
+library(sequins)
+library(dplyr)
+library(tidyr)
+library(ggplot2)
+```
+
+# Requête de base
+
+Afin de ne pas trop en demander à HAL, créons une requête de base qui n'envoient pas trop de requêtes d'un coup.
+
+```{r}
+hal_basic_request <- spq_init(
+ "hal",
+ request_control = spq_control_request(rate = 3/60)
+)
+
+```
+
+
+# Entrée par auteur·rice
+
+Essayons par exemple d'examiner s'il existe dans la base quelqu'un qui s'appelle (tout à fait au hasard) "Lise Vaudor":
+
+```{r test_LV}
+test_LV = hal_basic_request %>%
+ spq_add("?personne foaf:name 'Lise Vaudor'") %>% # récupère les personnes appelées "Lise Vaudor"
+ spq_perform()
+DT::datatable(test_LV)
+```
+
+Il existe bien une personne ayant ce nom dans la base de données, qui fait l'objet d'une [fiche consultable](`r test_LV$personne[1]`).
+
+La consultation de cette page montre que deux propriétés sont souvent renseignées: **foaf:interest** et **foaf:topic_interest**. Cette dernière propriété semble regrouper des mots-clés issus de l'ensemble des publications de l'auteur alors que foaf:interest correspond à des centres d'intérêt déclarés (probablement lors de la création du profil HAL: à vrai dire je ne m'en souviens plus!).
+
+Quoi qu'il en soit, l'information relative aux centres d'intérêt est accessible comme suit:
+
+```{r interet_LV, fig.width=7,fig.height=7}
+requete = hal_basic_request %>%
+ spq_add("?personne foaf:name 'Lise Vaudor'") %>%
+ spq_add("?personne foaf:interest ?interet") %>% # récupère les centres d'intérêt
+ spq_label(interet, .languages = "fr") # étiquette les centres d'intérêt
+
+sequins::graph_query(requete, layout = "tree")
+```
+
+
+```{r interet_LV_run}
+interet_LV = requete %>% # garde seulement les étiquettes en français
+ spq_perform()
+DT::datatable(interet_LV)
+```
+
+# Documents d'un·e auteur·rice
+
+Une des petites subtilités du modèle de données HAL consiste à considérer que **un document a un créateur·rice -- ou auteur·rice -- et un·e créateur·rice correspond à une personne**.
+
+## Affiliations
+
+Par exemple, l'article "How sampling influences the statistical power to detect changes in abundance: an application to river restoration" a pour créatrice (entre autres personnes) "Lise Vaudor à l'époque du Cemagref", qui correspond à la personne "Lise Vaudor" qui elle est intemporelle 😉.
+
+Ainsi, c'est en considérant les créateurs de documents que l'on va récupérer les affiliations: **l'affiliation est une information qui se récupère en adoptant une entrée par document plutôt que par auteur·rice**.
+
+
+```{r orga_LV_prep, fig.width=7, fig.height=8}
+requete = hal_basic_request %>%
+ spq_add("?doc dcterms:creator ?createur") %>% # documents crées par créateur
+ spq_add("?createur hal:structure ?affiliation") %>% # créateur correspond à une affiliation
+ spq_add("?createur hal:person ?personne") %>% # créateur correspond à une personne
+ spq_add("?personne foaf:name 'Lise Vaudor'") %>%
+ spq_label(affiliation, .overwrite = TRUE, .languages = NULL) %>% # étiquette affiliation
+ spq_group_by(affiliation) %>% # groupe par affiliation
+ spq_summarise(n = n()) %>%
+ spq_arrange(desc(n))
+
+requete
+
+sequins::graph_query(requete, layout="tree")
+```
+
+```{r orga_LV_run}
+orga_LV = requete %>% # renvoie le nombre d'enregistrements
+ spq_perform()
+
+DT::datatable(orga_LV)
+```
+
+## Documents
+
+Si l'on ne s'intéresse pas aux affiliations mais aux **documents** eux-mêmes:
+
+```{r docs_LV}
+docs_LV = hal_basic_request %>%
+ spq_add("?doc dcterms:creator ?createur") %>%
+ spq_add("?createur hal:structure ?affiliation") %>%
+ spq_add("?createur hal:person ?personne") %>%
+ spq_add("?personne foaf:name 'Lise Vaudor'") %>%
+ spq_label(affiliation, .overwrite = TRUE, .languages = NULL) %>%
+ spq_add("?doc dcterms:type ?type") %>%
+ spq_label(type, .languages = "fr") %>%
+ spq_add("?doc dcterms:bibliographicCitation ?citation") %>%
+ spq_add("?doc dcterms:issued ?date") %>%
+ spq_mutate(date = str_sub(as.character(date), 1, 4)) %>%
+ spq_group_by(citation, type_label, date) %>%
+ spq_summarise(affiliation = str_c(affiliation, sep = ", ")) %>%
+ spq_perform()
+
+docs_LV
+```
+
+Cette requête renvoie une table comptant `r nrow(docs_LV)`. Voici les 20 documents les plus récents:
+
+```{r docs_LV_recents}
+docs_LV %>%
+ arrange(desc(date)) %>%
+ head(20) %>%
+ DT::datatable()
+```
+
+
+# Entrée par laboratoire
+
+
+## Identification du laboratoire
+
+Intéressons-nous maintenant aux **publications issues d'un laboratoire**. Ici, nous avons choisi le laboratoire "Environnement Ville Société", alias "EVS" ou encore "UMR 5600".
+
+Essayons de le retrouver dans la base de données:
+
+```{r labo_EVS}
+labo_EVS = hal_basic_request %>%
+ spq_label(labo, .languages = NULL, .required = TRUE) %>%
+ spq_add("?labo dcterms:identifier ?labo_id", .required = FALSE) %>%
+ spq_filter(str_detect(labo_label,"EVS|(UMR 5600)|(Environnement Ville Soc)")) %>%
+ spq_perform()
+labo_EVS
+```
+
+Bon! Eh bien, étant donné la diversité des formats dans la dénomination d'EVS, un petit tri manuel s'impose.
+
+```{r labo_EVS_filter}
+labo_EVS = labo_EVS %>%
+ unique() %>%
+ mutate(num = 1:n()) %>%
+ filter(!(num %in% c(1,2,3,18))) %>% # ici je retire les labos qui ne correspondent pas à UMR 5600 / EVS
+ select(-num)
+DT::datatable(labo_EVS)
+```
+
+Créons maintenant une fonction qui permet de récupérer l'**ensemble des documents pour chacune de ces dénominations de laboratoire**.
+
+```{r get_docs_lab}
+get_docs_lab = function(lab){
+ Sys.sleep(30) # extra-safe
+ lab = paste0("<",lab,">")
+ result = hal_basic_request %>%
+ spq_add(glue::glue("?createur hal:structure {lab}")) %>%
+ spq_add("?createur hal:person ?personne") %>%
+ spq_add("?personne foaf:name ?auteur") %>%
+ spq_add("?doc dcterms:creator ?createur") %>%
+ spq_select(-createur) %>%
+ spq_label(type, .languages = "fr") %>% # étiquette le type de document en français
+ spq_add("?doc dcterms:bibliographicCitation ?citation") %>% # récupère la citation
+ spq_add("?doc dcterms:issued ?date") %>%
+ spq_perform() %>%
+ mutate(date = stringr::str_sub(date,1,4)) %>%
+ select(auteur, type = type_label, date, citation)
+ return(result)
+}
+```
+
+Appliquons maintenant cette fonction à chacune des dénominations possibles pour le labo EVS:
+
+```{r apply_get_docs_lab}
+docs_EVS = labo_EVS %>%
+ group_by(labo, labo_label) %>%
+ tidyr::nest() %>%
+ mutate(data = purrr::map(labo, get_docs_lab)) %>%
+ tidyr::unnest(cols="data")
+
+dim(docs_EVS)
+```
+
+Cette table compte de nombreux enregistrements. On montre ci-dessous les plus récents (à partir de 2020):
+
+```{r docs_EVS_show}
+docs_EVS_show = docs_EVS %>%
+ select(-labo) %>%
+ filter(date >= 2020) %>%
+ unique() %>%
+ select(auteur, date, type, citation, citation) %>%
+ ungroup()
+
+dim(docs_EVS_show)
+
+DT::datatable(docs_EVS_show)
+```
+
+# Rendus graphiques
+
+On peut dès lors utiliser ces données pour produire un **certain nombre de graphiques** permettant d'apprécier la production du laboratoire au cours du temps:
+
+```{r plot_datecitation}
+docs_datecitation = docs_EVS %>%
+ group_by(type) %>%
+ mutate(ntype = n()) %>%
+ ungroup() %>%
+ mutate(ntot = n()) %>%
+ mutate(proptype = ntype/ntot) %>%
+ filter(proptype > 0.05) %>%
+ group_by(date, citation, type) %>%
+ summarise(n = n()) %>%
+ filter(date > 2015)
+
+ggplot(docs_datecitation, aes(x = date, y = n, fill = type)) +
+ geom_bar(stat = "identity") +
+ facet_grid(rows = vars(type))
+```
+
+Il ne s'agit là que d'un exemple (parmi beaucoup d'autres possibilités comme l'exploitation de mots clés, de statistiques par journal, de réseaux d'auteurs) pour exploiter ces données. Nanmoins ces méthodes allant au-delà du "scope" du package glitter nous n'irons pas plus loin en terme d'analyse des résultats des requêtes dans ce document.
+