Analysing a literature¶
Once records are in hand, scopusflow turns them into the figures a bibliometric study usually needs, all from the one stable schema. The examples here run on the harvest bundled with the package, which holds 138 real articles on graphene supercapacitors published between 2015 and 2024. It stands in for a Scopus retrieval because retrieved records cannot be redistributed, and it lets every figure on this page be drawn without a key. The live call that would produce records for real is shown alongside, and Get started gives the fuller account of where the bundled set comes from.
Where the records come from¶
A live harvest is two calls, a query and a plan run through fetch_plan, and both need a configured key.
q = sf.scopus_query("graphene", "supercapacitor", field="TITLE-ABS-KEY")
plan = sf.SearchPlan(q, years=range(2015, 2025), partition="year")
records = sf.fetch_plan(plan, cache_dir="graphene-harvest")
example_records returns the bundled equivalent, already normalised into the same schema, which is what the rest of this page works on.
records = sf.example_records()
out(records[["title", "year", "publication", "citations"]].head(3))
| title | year | publication | citations |
|---|---|---|---|
| Enhanced Capacitive Properties of All-solid-state Symmetric Graphene Supercapacitors by Incorporating Nitrogen-doping and SnO2 Nanoparticles | 2015 | Journal of Inorganic Materials | 1 |
| Fabrication and Characterization of a Vertically-Oriented Graphene Supercapacitor | 2015 | DigitalCommons - CalPoly (California State Polytechnic University) | 0 |
| Flexible and Stackable Laser-Induced Graphene Supercapacitors | 2015 | ACS Applied Materials & Interfaces | 469 |
What is in a record set¶
top tallies the most frequent sources or authors. Author strings that hold several names are split, so each contributor is counted once per record.
out(sf.top(records, by="source", n=5))
out(sf.top(records, by="author", n=6))
| value | n |
|---|---|
| ACS Applied Materials & Interfaces | 8 |
| Journal of Power Sources | 5 |
| Synthetic Metals | 5 |
| Electrochimica Acta | 4 |
| Scientific Reports | 4 |
| value | n |
|---|---|
| Hao Yang | 3 |
| R. Mendoza | 3 |
| L. Ojeda | 3 |
| Nurbek Kakenov | 2 |
| Bin Wang | 2 |
| Sungsik Jo | 2 |
The tally has a long tail, as a topic literature usually does. ACS Applied Materials & Interfaces heads it with eight records, while 77 of the 90 journals represented appear only once or twice. The two records whose source title is missing are dropped from the tally, since an empty name is not a journal.
How a literature grows¶
year_counts is the offline tally of records per year from a set you already hold. Because the bundled harvest is a complete pull, these counts are the publications the query matched in each year.
trend = sf.year_counts(records)
out(trend)
| year | n |
|---|---|
| 2015 | 15 |
| 2016 | 9 |
| 2017 | 10 |
| 2018 | 15 |
| 2019 | 19 |
| 2020 | 13 |
| 2021 | 13 |
| 2022 | 15 |
| 2023 | 15 |
| 2024 | 14 |
scopus_trend instead asks the API for the count in each year without downloading the records, which is far cheaper when all you want is the shape of the growth. It needs a key, so it is shown but not run.
trend = sf.scopus_trend(q, years=range(2015, 2025))
Turn it into figures¶
With the optional plot extra installed, the summaries become matplotlib figures.
sf.plot_trend(sf.year_counts(records))
show()
sf.plot_top(sf.top(records, by="source"))
show()
Size a niche¶
Where the figures above summarise records already in hand, scopus_intersections sizes a set of concepts and their overlap straight from the count endpoint, one cheap request per row, so a whole landscape costs no harvest. A concept value can be a bare term, wrapped in field for you, or a complete field-tagged expression such as a synonym set, used as given.
sets = sf.scopus_intersections(
concepts={
"semantic priming": "semantic priming",
"mental simulation":
"TITLE-ABS-KEY(mental simulation) OR TITLE-ABS-KEY(embodied simulation)",
},
intersections=[["semantic priming", "mental simulation"]],
field="TITLE-ABS-KEY",
)
The result has a fixed shape, one row per concept and per intersection, which we reproduce here so the chart renders without a key. plot_scopus_intersections draws it as a lollipop chart on a log axis, with the intersection accented.
sets = pd.DataFrame({
"label": ["semantic priming", "mental simulation",
"semantic priming × mental simulation"],
"query": ["TITLE-ABS-KEY(semantic priming)",
"TITLE-ABS-KEY(mental simulation) OR "
"TITLE-ABS-KEY(embodied simulation)",
"(TITLE-ABS-KEY(semantic priming)) AND "
"(TITLE-ABS-KEY(mental simulation) OR "
"TITLE-ABS-KEY(embodied simulation))"],
"n": pd.array([6600, 2600, 18], dtype="Int64"),
"type": ["concept", "concept", "intersection"],
"size": [1, 1, 2],
"members": ["semantic priming", "mental simulation",
"semantic priming; mental simulation"],
})
focal = sets.loc[sets["type"] == "intersection", "label"].tolist()
sf.plot_scopus_intersections(sets, highlight=focal)
show()
Read the fuller record¶
scopus_abstract pulls the abstract and fuller metadata for a known identifier, and is resilient to the odd id that fails. It calls the Abstract Retrieval API, so it needs a key.
abstracts = sf.scopus_abstract(dois[:10], by="doi")
abstracts[["doi", "title", "year"]]
The result is one row per identifier, over the stable ABSTRACT_COLUMNS schema. The bundled harvest carries the bibliographic fields but no abstract text, so the frame below takes its two most-cited records and leaves the one column the corpus cannot supply as a placeholder. Everything else in those rows is the real record.
most_cited = records.nlargest(2, "citations")
abstracts = pd.DataFrame({
"scopus_id": pd.NA,
"doi": most_cited["doi"],
"title": most_cited["title"],
"abstract": "(the bundled harvest carries no abstract text)",
"publication": most_cited["publication"],
"date": most_cited["date"],
"year": most_cited["year"],
"citations": most_cited["citations"],
}, columns=sf.abstract.ABSTRACT_COLUMNS)
out(abstracts[["title", "publication", "year", "citations"]])
| title | publication | year | citations |
|---|---|---|---|
| Graphene for batteries, supercapacitors and beyond | Nature Reviews Materials | 2016 | 1247 |
| Flexible and Stackable Laser-Induced Graphene Supercapacitors | ACS Applied Materials & Interfaces | 2015 | 469 |
A failed identifier does not stop the batch, but yields an all-NA row that still records the id, together with a warning.