Abstract
This document provides the code for exploring how and by whom the Japan-returned students were discussed in the Chinese periodical Dongfang zazhi 東方雜誌 (Eastern Miscellany) from 1905 to 1948.
This document is part of a series dedicated to a corpus-based analysis of articles on Japan- and U.S.-returned students in Dongfang zazhi 東方雜誌 (The Eastern Miscellany). Building on a previous script aimed at constructing and exploring a corpus focused on Japan-returned students, this document provides code for extracting and analyzing biographical information about the authors of these articles. # Authorship Information
# clean authors' names
library(dplyr)
library(tidyr)
liuri_authors <- liuri_clean %>% select(DocId, authors) %>%
mutate(Author = str_replace_all(authors, "\\[", "")) %>%
mutate(Author = str_replace_all(Author, "\\]", ""))%>%
mutate(Author = str_replace_all(Author, "\\'", "")) %>%
separate_rows(Author, sep = ",\\s*")
liuri_authors
liuri_authors %>% group_by(Author) %>% count(sort = TRUE) # number of articles by author
liuri_authors %>% group_by(DocId) %>% count(sort = TRUE) # co-authored articles
We searched for biographical information on the authors in Chinese Wikipedia and the Who’s Who publications provided by the Institute of Modern History (IMH), Academia Sinica, Taipei.
# Create a function for multiple queries
multiple_search <- function(queries, corpus) {
results <- histtext::search_documents_ex(queries[1], corpus) %>%
mutate(Q=queries[1])
for(q in queries){
new_result <- histtext::search_documents_ex(q, corpus) %>%
mutate(Q=q)
results <- dplyr::bind_rows(results, new_result)
}
distinct(results)
}
# Create the list of names to query
liuri_authors_list <- liuri_authors %>% drop_na(Author) %>% filter(!Author == "留日學生") %>% mutate(Queries=str_glue('"{Author}"'))
library(histtext)
liuri_authors_wiki <- multiple_search(liuri_authors_list$Queries, "wikibio-zh") # 338 results
liuri_authors_wiki <- liuri_authors_wiki %>% group_by(Q) %>% add_tally()
# Eliminate irrelevant results
liuri_list_names <- liuri_authors_list$Author
liuri_list_names <- paste(liuri_list_names, sep = "", collapse = "|")
liuri_authors_wiki <- liuri_authors_wiki %>% mutate(title_match = str_extract(Title, liuri_list_names))
liuri_authors_wiki <- liuri_authors_wiki %>% group_by(title_match) %>% add_tally()
liuri_authors_wiki_match <- liuri_authors_wiki %>% filter(!is.na(title_match)) # 14 matches
# 14 bios remain
liuri_authors_wiki_match
# Extract the full text of biographies
liuri_authors_wiki_ft <- histtext::get_documents(liuri_authors_wiki_match, "wikibio-zh")
liuri_authors_wiki_ft
library(histtext)
liuri_authors_imh <- multiple_search(liuri_authors_list$Queries, "imh-zh") # 117 results
liuri_authors_imh <- liuri_authors_imh %>% mutate(title_match = str_extract(Title, liuri_list_names))
liuri_authors_imh <- liuri_authors_imh %>% group_by(title_match) %>% add_tally()
# Eliminate irrelevant results
liuri_authors_imh_match <- liuri_authors_imh %>% filter(!is.na(title_match)) # 69 results remain
liuri_authors_imh_match <- liuri_authors_imh_match %>% distinct(DocId, Title) %>%
mutate(Title_clean = str_replace(Title, "【", "")) %>%
mutate(Title_clean = str_replace(Title_clean, "】", "")) %>%
mutate(Title_clean = str_extract(Title_clean, "^.{3}")) %>% relocate(title_match, .after = Title_clean)
liuri_authors_imh_match <- liuri_authors_imh_match %>% mutate(title_length = nchar(Title)) %>% mutate(title_length2 = nchar(Title_clean)) %>%
mutate(query_length = nchar(title_match)) %>% mutate(dif = (query_length-title_length)) %>% mutate(dif2 = (query_length-title_length2))
liuri_authors_imh_filtered <- liuri_authors_imh_match %>% filter(!dif2 == "-1")
liuri_authors_imh_unique <- liuri_authors_imh_filtered %>%
select(DocId, title_match) %>% rename(Name = title_match) %>%
group_by(Name) %>% count()
liuri_authors_imh_filtered <- liuri_authors_imh_filtered %>% select(DocId, title_match) %>% rename(Name = title_match)
# 49 biographies remain, referring to 13 unique names (from 1 to 6 biographies per author)
liuri_authors_imh_filtered
# Retrieve full text
liuri_authors_imh_ft <- histtext::get_documents(liuri_authors_imh_filtered, "imh-zh")
liuri_authors_imh_ft
## Bind the two datasets
liuri_authors_bio <- bind_rows(liuri_authors_imh_ft, liuri_authors_wiki_ft)
# Retrieve year of birth
liuri_authors_bio$year <- regmatches(liuri_authors_bio$Text, gregexpr("\\d{4}", liuri_authors_bio$Text))
liuri_authors_bio$birth <- regmatches(liuri_authors_bio$year, regexpr("[[:digit:]]+", liuri_authors_bio$year))
liuri_authors_bio$year <- NULL
liuri_authors_bio_filtered <- liuri_authors_bio %>% filter(birth < 1948) %>% filter(birth > 1800) # 20 names remain
liuri_authors_bio_filtered
# Retrieve native provinces based on list
library(readr)
provinces <- read_delim("~/indexes/provinces.csv",
delim = ";", escape_double = FALSE, trim_ws = TRUE)
provinces <- provinces %>% na.omit()
# create vector
prov_list <- provinces$Province
prov_list <- paste(prov_list, sep = "", collapse = "|")
liuri_authors_bio_filtered <- liuri_authors_bio_filtered %>% mutate(birthplace = str_extract(Text, prov_list))
# Retrieve academic disciplines based on typology
# Load typology
library(readr)
disciplines <- read_delim("~/indexes/disciplines.csv",
delim = ";", escape_double = FALSE, trim_ws = TRUE)
# create vector
disc_list <- disciplines$Level2__ZhT_MCBD
disc_vec <- paste(disc_list, sep = "", collapse = "|")
liuri_authors_bio_filtered <- liuri_authors_bio_filtered %>%
mutate(discipline = str_extract_all(Text, disc_vec)) %>%
mutate(discipline = as.character(discipline))
# identify those who studied or traveled to foreign countries
liuri_authors_bio_filtered <- liuri_authors_bio_filtered %>%
mutate(edu_country = str_extract_all(Text, "留美|留日|留法|留德|留英")) %>%
mutate(edu_country = as.character(edu_country)) %>%
mutate(country = str_extract_all(Text, "美國|日本|法國|德國|英國")) %>%
mutate(country = as.character(country))
liuri_authors_bio_filtered
In the following section, we extract named entities from biographies using models specifically developed by the ENP-China team for modern Chinese historical texts, integrated into the HistText package.
liuri_authors_imh_ner <- ner_on_corpus(liuri_authors_imh_ft, corpus = "imh-zh")
liuri_authors_wiki_ner <- ner_on_corpus(liuri_authors_wiki_ft, corpus = "wikibio-zh")
liuri_authors_ner <- bind_rows(liuri_authors_imh_ner, liuri_authors_wiki_ner) # bind the two lists
liuri_authors_ner
In the following section, we focus on organizations to define
occupational profiles, but we could also examine other types of
entities, such as events in which they were involved or creative works
they produced during their careers.
# Filter organizations
liuri_authors_org <- liuri_authors_ner %>% filter(Type == "ORG")
# Preliminary cleaning
liuri_authors_org <- liuri_authors_org %>%
mutate(text_clean = str_replace(Text, "《", "")) %>%
mutate(text_clean = str_replace(text_clean, ">", "")) %>%
relocate(text_clean, .after = Text) %>%
mutate(text_clean, text_clean=str_replace(text_clean,"(.*","")) %>%
mutate(text_clean, text_clean=str_replace(text_clean,"\\(.*","")) %>%
mutate(text_clean, text_clean=str_replace(text_clean,"\\(.*",""))%>%
mutate(text_clean = str_replace(text_clean, " ", "")) %>%
mutate(text_clean = str_replace(text_clean, " ", ""))%>%
mutate(length = nchar(text_clean)) %>%
relocate(length, .after = text_clean)
liuri_authors_org <- liuri_authors_org %>% filter(length > 1) # 463
# Extract suffixes and prefixes to help classify and locate institutions
liuri_authors_org <- liuri_authors_org %>%
mutate(class = str_sub(text_clean,-2,-1)) %>%
relocate(class, .after = text_clean)
liuri_authors_org <- liuri_authors_org %>%
mutate(pre = str_sub(text_clean, 1, 2)) %>%
relocate(pre, .before = text_clean)
# Remove residual noise (position verbs, etc)
liuri_authors_org <- liuri_authors_org %>%
mutate(text_clean = str_replace(text_clean, "任", ""))%>%
mutate(text_clean = str_replace(text_clean, "入", ""))%>%
mutate(text_clean = str_replace(text_clean, "久", ""))%>%
mutate(text_clean = str_replace(text_clean, "于", ""))%>%
mutate(text_clean = str_replace(text_clean, "於", ""))%>%
mutate(text_clean = str_replace(text_clean, "從", "")) %>%
mutate(length = nchar(text_clean)) %>%
filter(length > 1) %>% #
mutate(pre = str_sub(text_clean, 1, 2))
liuri_authors_org <- liuri_authors_org %>%
filter(stringr::str_detect(liuri_authors_org$text_clean, "[\\p{Han}]"))
# 461 organizations remain
# Most important institutions (altogether, across biographies)
liuri_authors_org %>% group_by(text_clean) %>%
count(sort = TRUE)
liuri_authors_org %>% distinct(DocId, text_clean) %>%
group_by(text_clean) %>% count(sort = TRUE)
# Most important types of institutions
liuri_authors_org %>% distinct(DocId, text_clean, class) %>%
group_by(class) %>% count(sort = TRUE)
Finally, we export the list of authors with extracted
information for manual verification to remove redundant or irrelevant
results. We also export the list of organizational affiliations to
standardize and categorize the authors and their occupations.
write.csv(liuri_authors_org, "~/output/liuri_authors_org.csv")
write.csv(liuri_authors_bio_filtered, "~/output/liuri_authors_bio_filtered.csv")
# Reimport curated list of authors and their attributes
library(readr)
liuri_authors_to_analyze <- read_delim("~/liuri_authors_to_analyze.csv",
delim = ";", escape_double = FALSE, trim_ws = TRUE)
# Replace empty fields with NAs
liuri_authors_to_analyze <-liuri_authors_to_analyze %>%
mutate(across(everything(), ~ifelse(.=="", NA, as.character(.))))
liuri_authors_to_analyze
liuri_authors_to_analyze %>% group_by(Nationality) %>% count(sort = TRUE)
liuri_authors_to_analyze %>% group_by(Generation) %>% count()
library(hrbrthemes)
library(viridis)
liuri_authors_to_analyze %>% drop_na(BirthYear) %>%
mutate(BirthYear = as.numeric(BirthYear))%>%
ggplot( aes(x=BirthYear)) +
geom_histogram( binwidth=1, fill="#69b3a2", color="#e9ecef", alpha=0.9) +
ggtitle("Bin size = 1") +
theme_ipsum() +
theme(
plot.title = element_text(size=15)
) +
labs(title = "Authors' Year of Birth (留日)",
x = "Year",
y = "Frequency")
### Native Place
liuri_authors_to_analyze %>% group_by(Birthplace) %>% count(sort = TRUE)
liuri_authors_to_analyze %>% group_by('Country of Education') %>% count(sort = TRUE)
liuri_authors_to_analyze %>% group_by('Education Country') %>% count(sort = TRUE)
liuri_authors_to_analyze %>% group_by(Occupation) %>% count(sort = TRUE)
liuri_authors_to_analyze %>% group_by(Occupation2) %>% count(sort = TRUE)
liuri_authors_to_analyze %>% group_by(Specialization) %>% count(sort = TRUE)
liuri_authors_to_analyze %>% group_by(Party) %>% count(sort = TRUE)
Note: DL = Democratic League. GMD = Guomindang.
TMH = Tongmenghui.
In the final section, we employed Multiple Correspondence Analysis (MCA)—a statistical method used to identify correlations between categorical attributes and to cluster individuals with similar profiles. This analysis aims to examine how biographical factors—generation, native place, education, and occupation—correlate with the topics authors engaged with and the overall sentiment (positive or negative) they expressed toward Japanese- and American-returned students.
liuri_mca <- liuri_authors_to_analyze %>% select(Name, Generation, 'Education Country', Occupation, Sentiment, Topic)
liuri_mca <- liuri_mca %>% drop_na(Generation) # 38 remain
liuri_mca <- column_to_rownames(liuri_mca, "Name")
liuri_mca
library(FactoMineR)
res.MCA<-MCA(liuri_mca,graph=FALSE)
# Plot
plot.MCA(res.MCA, choix='var',title="Category Plot (留日)",col.var=c(1,2,3,4,5))
plot.MCA(res.MCA,col.var=c(1,1,2,2,2,2,3,3,3,3,3,3,4,4,5,5,5,5,5),title="Biplot (留日)", cex=0.8,cex.main=0.8,cex.axis=0.8, autoLab = "yes", label =c('ind','var'))
plot.MCA(res.MCA,invisible= 'ind',col.var=c(1,1,2,2,2,2,3,3,3,3,3,3,4,4,5,5,5,5,5),title="Biplot: Variables (留日)", label =c('var'))
plot.MCA(res.MCA,invisible= 'var',title="Biplot: Individuals (留日)", autoLab = "yes", label =c('ind'))
# Statistics
dimdesc(res.MCA)
## $`Dim 1`
##
## Link between the variable and the categorical variable (1-way anova)
## =============================================
## R2 p.value
## Occupation 0.7709533 2.148266e-09
## Sentiment 0.4218280 1.024995e-05
## Topic 0.5135315 6.499835e-05
## Education Country 0.3818629 8.607131e-04
##
## Link between variable and the categories of the categorical variables
## ================================================================
## Estimate p.value
## Occupation=official-bureaucrat 1.1633233 4.228327e-08
## Sentiment=Negative 0.4203240 1.024995e-05
## Education Country=Japan-USA 1.1050754 3.762293e-04
## Topic=T1. Sino-Japanese Tensions 0.4902976 2.864683e-03
## Topic=T3. Regulations/Petitions 0.6574203 1.252314e-02
## Occupation=Occupation.NA -0.5183219 4.802206e-02
## Occupation=scholar -0.5934239 4.345915e-02
## Education Country=China-NA -0.6037227 8.390405e-03
## Topic=T2. Education/Political Reforms -0.6425274 6.407185e-03
## Sentiment=Positive -0.4203240 1.024995e-05
##
## $`Dim 2`
##
## Link between the variable and the categorical variable (1-way anova)
## =============================================
## R2 p.value
## Education Country 0.7093506 3.052458e-09
## Occupation 0.6645913 7.827675e-07
## Topic 0.4276463 8.083377e-04
## Generation 0.1771280 8.508663e-03
##
## Link between variable and the categories of the categorical variables
## ================================================================
## Estimate p.value
## Education Country=USA 1.1169567 1.395572e-09
## Occupation=scholar 0.3925588 1.557418e-04
## Occupation=other 1.7668460 1.222569e-03
## Topic=T5. Science/Society 0.4605570 2.113793e-03
## Generation=Post1895 0.2680503 8.508663e-03
## Occupation=Occupation.NA -0.4671254 2.311983e-02
## Topic=T2. Education/Political Reforms -0.4208162 2.127080e-02
## Generation=Pre1895 -0.2680503 8.508663e-03
## Education Country=China-NA -0.4651175 1.757432e-04
##
## $`Dim 3`
##
## Link between the variable and the categorical variable (1-way anova)
## =============================================
## R2 p.value
## Occupation 0.7525211 7.167313e-09
## Education Country 0.4959088 3.014586e-05
## Generation 0.2287223 2.389528e-03
## Sentiment 0.1555015 1.429194e-02
## Topic 0.2855281 2.225784e-02
##
## Link between variable and the categories of the categorical variables
## ================================================================
## Estimate p.value
## Education Country=Japan-USA 0.9837227 0.0007376626
## Occupation=official-bureaucrat 0.8010895 0.0017044975
## Generation=Pre1895 0.2978747 0.0023895278
## Education Country=Japan 0.1281767 0.0129134879
## Sentiment=Positive 0.2445848 0.0142919370
## Topic=T5. Science/Society 0.4540580 0.0188378544
## Occupation=scholar-official 1.3086641 0.0220182770
## Occupation=scholar 0.2613957 0.0266810092
## Occupation=professional writer -0.5554794 0.0449019649
## Topic=T3. Regulations/Petitions -0.4946911 0.0339162669
## Occupation=other -1.4185423 0.0295543993
## Sentiment=Negative -0.2445848 0.0142919370
## Occupation=Occupation.NA -0.3971275 0.0119155003
## Generation=Post1895 -0.2978747 0.0023895278
## Education Country=China-NA -0.6437582 0.0006121810
Finally, hierarchical clustering is applied to categorize authors based on shared characteristics:
res.MCA<-MCA(liuri_mca,ncp=14,graph=FALSE)
res.HCPC<-HCPC(res.MCA,nb.clust=5,consol=FALSE,graph=FALSE)
# Plots
plot.HCPC(res.HCPC,choice='tree',title='Tree Map (留日)')
plot.HCPC(res.HCPC,choice='map',draw.tree=FALSE,title='Factor Map (留日)')
plot.HCPC(res.HCPC,choice='3D.map',ind.names=FALSE,centers.plot=FALSE,angle=60,title='3D-Tree Map (留日)')
# Statistics
summary(res.HCPC)
## Length Class Mode
## data.clust 6 data.frame list
## desc.var 3 catdes list
## desc.axes 3 catdes list
## desc.ind 2 -none- list
## call 7 -none- list
For a comparative perspective, please consult the corresponding scripts on American-returned students.