= FALSE recompileData
Bibliometric analysis of the field of soft robotics
1 Notes
I derived 12,363 documents from https://www.webofscience.com/ with the following search terms:
(“soft robot” OR “soft robotics”)
Date of retrieval: 24th of July 2025 (references were sorted by “Date: newest first”)
2 global variables
Define your global variables (e.g., to run specific processes only once to save computation time):
3 load packages, additional functions, .bib files
### load packages
require(pacman)
p_load('bibliometrix', 'tidyverse')
### load .bib files
if(recompileData){
# List all .bib files in your working directory
<- list.files("data", pattern = "\\.bib$", full.names = TRUE)
bib_files print(bib_files)
# bib_files <- "data/savedrecs12001_12363.bib" # for testing
# Convert all of them in one go
<- convert2df(file = bib_files, dbsource = "wos", format = "bibtex", remove.duplicates = TRUE)
M
rm(bib_files)
setwd("data")
saveRDS(object = M, file = "M_out.rds")
else{
}setwd("outputs")
<- readRDS(file = "M_out.rds")
M }
3.1 additional functions
## APA7 style for plots
<- function() {
theme_apa7 theme_minimal(base_size = 12, base_family = "sans") +
theme(
plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
plot.subtitle = element_text(size = 12, hjust = 0.5),
axis.title = element_text(face = "bold"),
axis.text = element_text(size = 11),
panel.grid.major = element_line(color = "gray85"),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
axis.line = element_line(color = "black")
)
}
## Extract information of identified clusters
<- function(cluster_df, min_cluster_size = 6, top_n = 3) {
get_top_articles_by_cluster # Count clusters and articles per cluster
<- cluster_df %>%
cluster_sizes count(cluster, name = "ClusterSize")
# Filter clusters with at least `min_cluster_size` articles
<- cluster_sizes %>%
eligible_clusters filter(ClusterSize >= min_cluster_size) %>%
pull(cluster)
# For each eligible cluster, get top N articles by btw_centrality
<- cluster_df %>%
top_articles filter(cluster %in% eligible_clusters) %>%
group_by(cluster) %>%
arrange(desc(btw_centrality)) %>%
slice_head(n = top_n) %>%
ungroup()
# Return both total clusters and result table
list(
total_clusters = n_distinct(cluster_df$cluster),
eligible_clusters = length(eligible_clusters),
top_articles = top_articles
) }
3.2 remove all entries without DOIs
Remark: despite downloading 12,363 documents, it is not possible to download all such retrieved documents (e.g., missing entries)
Percentage of entries removed:
nrow(M)
[1] 11352
round(x = sum(is.na(M$DI)) / length(M$DI) * 100, digits = 2)
[1] 8.78
<- M[!is.na(M$DI), ]
M nrow(M)
[1] 10355
4 📊 Descriptive bibliometric analysis
<- biblioAnalysis(M, sep = ";")
results <- summary(results, k=10, pause=FALSE) S
MAIN INFORMATION ABOUT DATA
Timespan 1997 : 2025
Sources (Journals, Books, etc) 1363
Documents 10355
Annual Growth Rate % 29.04
Document Average Age 3.35
Average citations per doc 32.26
Average citations per year per doc 5.579
References 225387
DOCUMENT TYPES
article 7591
article article 1
article; book chapter 21
article; data paper 1
article; early access 256
article; proceedings paper 40
article; retracted publication 1
correction 11
editorial material 119
letter 5
meeting abstract 2
news item 2
proceedings paper 1548
review 727
review; book chapter 3
review; early access 27
DOCUMENT CONTENTS
Keywords Plus (ID) 6821
Author's Keywords (DE) 17686
AUTHORS
Authors 21950
Author Appearances 59078
Authors of single-authored docs 161
AUTHORS COLLABORATION
Single-authored docs 198
Documents per Author 0.472
Co-Authors per Doc 5.71
International co-authorships % 26.41
Annual Scientific Production
Year Articles
1997 1
2003 1
2005 2
2006 6
2007 2
2008 4
2009 5
2010 4
2011 12
2012 22
2013 26
2014 91
2015 127
2016 175
2017 320
2018 509
2019 933
2020 1105
2021 1032
2022 913
2023 1708
2024 2097
2025 1260
Annual Percentage Growth Rate 29.04
Most Productive Authors
Authors Articles Authors Articles Fractionalized
1 WANG Y 269 WANG Y 46.8
2 LI Y 256 LI Y 39.4
3 ZHANG Y 231 WANG Z 37.2
4 WANG Z 220 ZHANG Y 31.7
5 LIU Y 207 WANG X 31.6
6 WANG X 207 LIU Y 30.3
7 CHEN Y 185 LIU J 28.9
8 WANG H 171 CHEN Y 28.3
9 LIU J 168 WANG J 26.9
10 WANG J 162 WANG H 26.7
Top manuscripts per citations
Paper DOI TC TCperYear NTC
1 RUS D, 2015, NATURE 10.1038/nature14543 4343 394.8 35.97
2 AMJADI M, 2016, ADV FUNCT MATER 10.1002/adfm.201504755 2616 261.6 23.51
3 WANG S, 2018, NATURE 10.1038/nature25494 1806 225.8 20.10
4 SHEPHERD RF, 2011, PROC NATL ACAD SCI U S A 10.1073/pnas.1116564108 1739 115.9 4.97
5 KIM Y, 2018, NATURE 10.1038/s41586-018-0185-0 1690 211.2 18.81
6 KIM S, 2013, TRENDS BIOTECHNOL 10.1016/j.tibtech.2013.03.002 1585 121.9 6.44
7 DICKEY MD, 2017, ADV MATER 10.1002/adma.201606425 1409 156.6 16.18
8 ILIEVSKI F, 2011, ANGEW CHEM-INT EDIT 10.1002/anie.201006464 1402 93.5 4.00
9 SHINTAKE J, 2018, ADV MATER 10.1002/adma.201707035 1352 169.0 15.05
10 TEE BCK, 2012, NAT NANOTECHNOL 10.1038/NNANO.2012.192 1250 89.3 5.78
Corresponding Author's Countries
Country Articles Freq SCP MCP MCP_Ratio
1 CHINA 3287 0.3204 2604 683 0.208
2 USA 1997 0.1946 1621 376 0.188
3 KOREA 654 0.0637 525 129 0.197
4 JAPAN 600 0.0585 521 79 0.132
5 UNITED KINGDOM 517 0.0504 304 213 0.412
6 ITALY 515 0.0502 319 196 0.381
7 GERMANY 339 0.0330 197 142 0.419
8 SINGAPORE 261 0.0254 155 106 0.406
9 SWITZERLAND 261 0.0254 148 113 0.433
10 AUSTRALIA 187 0.0182 119 68 0.364
SCP: Single Country Publications
MCP: Multiple Country Publications
Total Citations per Country
Country Total Citations Average Article Citations
1 USA 110293 55.23
2 CHINA 89020 27.08
3 ITALY 17964 34.88
4 KOREA 17837 27.27
5 GERMANY 13883 40.95
6 SINGAPORE 10880 41.69
7 UNITED KINGDOM 10127 19.59
8 SWITZERLAND 9652 36.98
9 JAPAN 9238 15.40
10 AUSTRALIA 6831 36.53
Most Relevant Sources
Sources Articles
1 SOFT ROBOTICS 690
2 IEEE ROBOTICS AND AUTOMATION LETTERS 629
3 ACS APPLIED MATERIALS \\& INTERFACES 298
4 ADVANCED FUNCTIONAL MATERIALS 257
5 ADVANCED MATERIALS 245
6 ADVANCED INTELLIGENT SYSTEMS 228
7 ADVANCED MATERIALS TECHNOLOGIES 175
8 SMART MATERIALS AND STRUCTURES 163
9 2023 IEEE INTERNATIONAL CONFERENCE ON SOFT ROBOTICS ROBOSOFT 143
10 2024 IEEE 7TH INTERNATIONAL CONFERENCE ON SOFT ROBOTICS ROBOSOFT 143
Most Relevant Keywords
Author Keywords (DE) Articles Keywords-Plus (ID) Articles
1 SOFT ROBOTICS 2315 DESIGN 2103
2 SOFT ROBOT 692 FABRICATION 877
3 SOFT 525 ACTUATORS 494
4 ACTUATORS 443 SOFT 488
5 ROBOTS 370 DRIVEN 461
6 ROBOTICS 355 BEHAVIOR 321
7 3D PRINTING 346 LOCOMOTION 312
8 SOFT ROBOTS 296 MODEL 291
9 CONTROL 237 COMPOSITES 280
10 SOFT ACTUATOR 235 PERFORMANCE 279
Plot for Annual Number of Published Articles:
# Step 1: Aggregate number of articles per year
<- data.frame(Year = results$Years) %>%
annual_articles group_by(Year) %>%
summarise(ArticleCount = n()) %>%
arrange(Year)
# Step 2: Get first and last year
<- min(annual_articles$Year)
first_year <- max(annual_articles$Year)
last_year
# Step 3: Generate x-axis breaks including first and last year
<- unique(c(first_year,
x_breaks pretty(annual_articles$Year, n = 8),
last_year))
# Step 4: Plot with x-axis including first and last year
ggplot(annual_articles, aes(x = Year, y = ArticleCount)) +
geom_line(linewidth = 1.1, color = "black") +
geom_point(size = 2.5, color = "black") +
geom_text(aes(label = ArticleCount),
vjust = -0.7, size = 3.2, color = "black") +
labs(
title = "Annual Scientific Production",
x = "Year",
y = "Number of Articles"
+
) scale_x_continuous(breaks = sort(unique(x_breaks))) +
scale_y_continuous(expand = expansion(mult = c(0, 0.1))) +
theme_apa7()
Plot for Annual Citations:
# Load required packages
library(dplyr)
library(ggplot2)
# Step 1: Aggregate total citations per year
<- data.frame(Year = results$Years, Citations = results$TCperYear) %>%
annual_citations group_by(Year) %>%
summarise(TotalCitations = sum(Citations, na.rm = TRUE)) %>%
arrange(Year)
# Step 2: Extract first and last year
<- min(annual_citations$Year)
first_year <- max(annual_citations$Year)
last_year
# Step 3: Generate x-axis breaks including first and last year
<- sort(unique(c(first_year,
x_breaks pretty(annual_citations$Year, n = 8),
last_year)))
# Step 4: Plot with explicit x-axis breaks
ggplot(annual_citations, aes(x = Year, y = TotalCitations)) +
geom_line(linewidth = 1.1, color = "black") +
geom_point(size = 2.5, color = "black") +
geom_text(aes(label = round(TotalCitations, 1)),
vjust = -0.7, size = 3.2, color = "black") +
labs(
title = "Annual Citations",
x = "Year",
y = "Total Citations"
+
) scale_x_continuous(breaks = x_breaks) +
scale_y_continuous(expand = expansion(mult = c(0, 0.1))) +
theme_apa7()
4.2 most important affiliations
Remark: only the top 50 are shown
::datatable(data = results$Aff_frac[1:50,]) DT
4.3 which country is leading the field:
Remark: only the country of the first author is considered
# Step 1: Prepare data
<- data.frame(
df Year = results$Years,
Country = str_trim(results$CO),
stringsAsFactors = FALSE
)
# Step 2: Get top 6 countries
<- df %>%
top_countries count(Country, sort = TRUE) %>%
slice_head(n = 6) %>%
pull(Country)
# Step 3: Aggregate by year and country
<- df %>%
top_country_year filter(Country %in% top_countries) %>%
count(Year, Country, name = "ArticleCount")
# Step 4: Plot with legend
ggplot(top_country_year, aes(x = Year, y = ArticleCount, color = Country, group = Country)) +
geom_line(linewidth = 1.1) +
geom_point(size = 2) +
geom_text(aes(label = ArticleCount), vjust = -0.6, size = 3.1, show.legend = FALSE) +
labs(
title = "Annual Scientific Production – Top 6 Countries",
x = "Year",
y = "Number of Articles",
color = "Country" # Legend title
+
) scale_x_continuous(breaks = pretty(unique(df$Year), n = 6)) +
scale_y_continuous(expand = expansion(mult = c(0, 0.1))) +
theme_apa7()
4.4 look out for Shelly and Falk:
despite Shelly having 55 articles listed in Web of Science (see: https://www.webofscience.com/wos/woscc/summary/35dc76f0-d712-4ae6-8cae-b563137dbca2-017054c94a/date-descending/1), in no title/ abstract the search terms
(“soft robot” OR “soft robotics”)
could be found
# Shelly:
sum(str_detect(M$AU, regex("Levy-Tzedek", ignore_case = TRUE)))
[1] 0
# Authors:
$AU[str_detect(M$AU, regex("Levy-Tzedek", ignore_case = TRUE))] M
character(0)
# DOIs:
$DI[str_detect(M$AU, regex("Levy-Tzedek", ignore_case = TRUE))] M
character(0)
# Falk:
sum(str_detect(M$AU, regex("Tauber F", ignore_case = TRUE)))
[1] 4
# Authors:
$AU[str_detect(M$AU, regex("Tauber F", ignore_case = TRUE))] M
[1] "TAUBER F;DESMULLIEZ M;PICCIN O;STOKES A;A. A"
[2] "TAUBER FJ;SLESARENKO V"
[3] "MEDER F;BAYTEKIN B;DEL DOTTORE E;MEROZ;YASMINE Y;TAUBER F;WALKER I;MAZZOLAI B"
[4] "CONRAD S;SPECK T;TAUBER F"
# DOIs:
$DI[str_detect(M$AU, regex("Tauber F", ignore_case = TRUE))] M
[1] "10.1088/1748-3190/acbb48" "10.3389/frobt.2023.1129827" "10.1088/1748-3190/aca198"
[4] "10.1007/978-3-030-64313-3\\_6"
5 📘 Bibliographic Coupling vs. Co-Citation
These methods both assess the similarity between documents, but from opposite directions in the citation network:
Metric | Bibliographic Coupling | Co-Citation |
---|---|---|
Perspective | Forward-looking (shared references) | Backward-looking (cited together) |
Definition | Two documents cite the same third document | Two documents are both cited by a later document |
Stabilizes Over Time? | ✅ Yes – reference list is fixed when published | ❌ No – co-citation grows over time as more papers cite both |
Used For | Measuring current similarity of documents | Mapping historic/latent structure of a field |
Bibliographic Coupling between references:
- Purpose: Creates a document-to-document network.
- Meaning: Two papers are linked if they cite the same reference(s).
- Use case: Reveal thematic similarity or topical clusters among papers.
!!! my computer is not capable to run this analyses for the complete data set (only subset of first 2000 documents):
<- biblioNetwork(M[1:2000,], analysis = "coupling", network = "references", sep = ";")
bc_matrix <- networkPlot(bc_matrix, n=30, Title="Bibliographic Coupling", type="fruchterman", labelsize=0.7, cluster = "fast_greedy") bc_network
rm(bc_matrix) # remove object to free RAM
# if you want to understand the meaning on the single cluster it is recommended to read the most 2-3 central article of the respective cluster:
<- get_top_articles_by_cluster(cluster_df = bc_network$cluster_res, min_cluster_size = 6, top_n = 3)
bc_network_summary $top_articles bc_network_summary
# A tibble: 6 × 5
vertex cluster btw_centrality clos_centrality pagerank_centrality
<chr> <dbl> <dbl> <dbl> <dbl>
1 alu a, 2025 1 19.1 0.0208 0.0269
2 long y, 2025 1 19.1 0.0208 0.0269
3 sun w, 2025 1 19.1 0.0208 0.0269
4 zhang c, 2025-3 2 3.54 0.0179 0.0369
5 xue w, 2025-1 2 3.54 0.0179 0.0369
6 narayanan p, 2025 2 3.54 0.0179 0.0369
Co-citation between references:
- Purpose: Creates a network of references that are frequently cited together.
- Meaning: Two references are linked if they are cited together by a third paper.
- Use case: Map intellectual foundations or classic works frequently grouped by others.
!!! my computer is not capable to run this analyses for the complete data set (only subset of last 1000 documents):
<- biblioNetwork(M[9000:nrow(M),], analysis = "co-citation", network = "references", sep = ";")
cc_matrix <- networkPlot(cc_matrix, n=30, Title="co-citation", type="fruchterman", labelsize=0.7, cluster = "fast_greedy") cc_network
rm(cc_matrix) # remove object to free RAM
# if you want to understand the meaning on the single cluster it is recommended to read the most 2-3 central article of the respective cluster:
<- get_top_articles_by_cluster(cluster_df = cc_network$cluster_res, min_cluster_size = 6, top_n = 3)
cc_network_summary $top_articles cc_network_summary
# A tibble: 6 × 5
vertex cluster btw_centrality clos_centrality pagerank_centrality
<chr> <dbl> <dbl> <dbl> <dbl>
1 zolfagharian a 2016-1 1 24.6 0.0238 0.0301
2 kim s 2013-1 1 23.4 0.0238 0.0301
3 majidi c 2014 1 22.6 0.0238 0.0301
4 rus d 2015 2 7.02 0.0217 0.0360
5 wehner m 2016 2 7.02 0.0217 0.0360
6 ilievski f 2011-1 2 7.02 0.0217 0.0360
6 🌐 Collaboration networks
between countries:
# Country collaboration
<- metaTagExtraction(M, Field = "AU_CO", sep = ";")
M <- biblioNetwork(M, analysis="collaboration", network="countries", sep=";")
net_cty <- networkPlot(net_cty, n=50, Title="Country Collaboration", type="fruchterman", size=TRUE, labelsize=0.7) tmp
## the top 10 collaborating countries:
$cluster_res[order(tmp$cluster_res$btw_centrality, decreasing = TRUE),][1:10,] tmp
vertex cluster btw_centrality clos_centrality pagerank_centrality
5 united kingdom 1 133.03583 0.01515152 0.03021562
1 china 5 78.47044 0.01492537 0.02920869
2 usa 5 77.93218 0.01492537 0.02938908
7 germany 5 77.53385 0.01515152 0.02987237
4 italy 5 61.02593 0.01449275 0.02907677
10 australia 2 60.56359 0.01408451 0.03056287
13 canada 1 50.96416 0.01315789 0.02732532
11 netherlands 5 45.09749 0.01408451 0.02681110
9 switzerland 1 43.87449 0.01315789 0.02616385
29 poland 2 34.86812 0.01369863 0.02281280
between authors (research groups):
# Author collaboration
<- biblioNetwork(M, analysis="collaboration", network="authors", sep=";")
net_aut <- networkPlot(net_aut, n=50, Title="Author Collaboration", type="fruchterman", labelsize=0.5, edges.min = 3) tmp
## the top 10 collaborating authors:
$cluster_res[order(tmp$cluster_res$btw_centrality, decreasing = TRUE),][1:10,] tmp
vertex cluster btw_centrality clos_centrality pagerank_centrality
12 chen x 2 211.48615 0.015873016 0.02158052
7 chen y 3 159.96875 0.014285714 0.02418322
22 wang l 3 79.81346 0.013333333 0.01596452
20 liu z 2 65.02344 0.012820513 0.01559453
16 yang y 3 64.01719 0.011904762 0.01237944
48 wang m 2 50.42152 0.009259259 0.01521823
37 yang h 2 48.11193 0.012820513 0.01328925
2 li y 1 39.76918 0.011764706 0.04466039
31 li h 3 38.32660 0.012820513 0.01157194
35 wu y 3 31.64626 0.012048193 0.01414629
7 📌 Conceptual structure (keywords co-occurrence)
Remark: also possible for abstracts
<- biblioNetwork(M, analysis="co-occurrences", network="keywords", sep=";")
net_key <- networkPlot(net_key, n=30, normalize="association", weighted=TRUE,
tmp Title="Keyword Co‑occurrence", type="fruchterman", size=TRUE, labelsize=0.7)