Este capítulo describe las 331 publicaciones que forman la base del análisis bibliométrico. Los artículos fueron descargados de Web of Science (WoS) y corresponden a trabajos que aplican al menos una técnica estadística multivariada en el contexto de la investigación turística.
Carga de datos
Ver código
from co_occurrence.io.loader import load_wos_datafrom co_occurrence.config import DATA_FILEdf = load_wos_data(DATA_FILE)print(f"Artículos cargados : {len(df)}")print(f"Columnas disponibles: {df.shape[1]}")print(f"Rango de años : {int(df['Publication Year'].min())} - {int(df['Publication Year'].max())}")
Artículos cargados : 331
Columnas disponibles: 72
Rango de años : 2017 - 2024
Distribución temporal
Ver código
import plotly.express as pxyear_counts = ( df["Publication Year"] .dropna() .astype(int) .value_counts() .sort_index() .reset_index())year_counts.columns = ["Año", "Artículos"]fig = px.bar( year_counts, x="Año", y="Artículos", title="Distribución temporal del corpus (331 artículos WoS)", labels={"Año": "Año de publicación", "Artículos": "N artículos"}, text="Artículos", height=420,)fig.update_traces(marker_color="#1f77b4", textposition="outside")fig.update_layout(xaxis={"dtick": 1})fig.show()
Número de artículos publicados por año
Top 10 revistas
Ver código
import pandas as pdjournal_col ="Source Title"if"Source Title"in df.columns else"Journal"if journal_col in df.columns: top_journals = ( df[journal_col] .dropna() .value_counts() .head(10) .reset_index() ) top_journals.columns = ["Revista", "Artículos"] fig2 = px.bar( top_journals, x="Artículos", y="Revista", orientation="h", title="Top 10 revistas por número de artículos", labels={"Artículos": "N artículos", "Revista": ""}, text="Artículos", height=420, ) fig2.update_layout(yaxis={"categoryorder": "total ascending"}) fig2.update_traces(marker_color="#ff7f0e", textposition="outside") fig2.show()else:print("Columna de revista no encontrada. Columnas disponibles:", list(df.columns[:10]))
Revistas con mayor número de artículos en el corpus
Tabla interactiva de revistas
Ver código
try:from itables import showif journal_col in df.columns: journals_full = ( df[journal_col] .dropna() .value_counts() .reset_index() ) journals_full.columns = ["Revista", "Artículos"] show( journals_full, caption="Revistas en el corpus (todas)", lengthMenu=[10, 25, 50], scrollY="400px", )exceptImportError:print("itables no disponible. Instalar con: pip install itables")if journal_col in df.columns: display( df[journal_col] .dropna() .value_counts() .head(20) .to_frame("Artículos") )
Loading ITables v2.7.3 from the internet...
(need help?)
Cobertura de keywords
Ver código
ak_col ="Author Keywords"kp_col ="Keywords Plus"has_ak = df[ak_col].notna().sum() if ak_col in df.columns else0has_kp = df[kp_col].notna().sum() if kp_col in df.columns else0has_both = ( (df[ak_col].notna() & df[kp_col].notna()).sum()if ak_col in df.columns and kp_col in df.columnselse0)has_none =len(df) - (df[ak_col].notna() | df[kp_col].notna()).sum() if ak_col in df.columns and kp_col in df.columns else"N/A"print(f"Artículos con Author Keywords : {has_ak} ({100*has_ak/len(df):.1f}%)")print(f"Artículos con Keywords Plus : {has_kp} ({100*has_kp/len(df):.1f}%)")print(f"Artículos con ambas : {has_both} ({100*has_both/len(df):.1f}%)")print(f"Artículos sin ninguna : {has_none}")
Artículos con Author Keywords : 322 (97.3%)
Artículos con Keywords Plus : 290 (87.6%)
Artículos con ambas : 284 (85.8%)
Artículos sin ninguna : 3
Note
La estrategia de preprocesamiento usa Author Keywords como fuente primaria y complementa con Keywords Plus únicamente para los artículos que carecen de keywords de autor. Esto maximiza la cobertura sin duplicar información.
Source Code
---title: "Descripción del corpus"---Este capítulo describe las 331 publicaciones que forman la base del análisis bibliométrico.Los artículos fueron descargados de Web of Science (WoS) y corresponden a trabajos que aplicanal menos una técnica estadística multivariada en el contexto de la investigación turística.## Carga de datos```{python}#| label: load-datafrom co_occurrence.io.loader import load_wos_datafrom co_occurrence.config import DATA_FILEdf = load_wos_data(DATA_FILE)print(f"Artículos cargados : {len(df)}")print(f"Columnas disponibles: {df.shape[1]}")print(f"Rango de años : {int(df['Publication Year'].min())} - {int(df['Publication Year'].max())}")```## Distribución temporal```{python}#| label: year-distribution#| fig-cap: "Número de artículos publicados por año"import plotly.express as pxyear_counts = ( df["Publication Year"] .dropna() .astype(int) .value_counts() .sort_index() .reset_index())year_counts.columns = ["Año", "Artículos"]fig = px.bar( year_counts, x="Año", y="Artículos", title="Distribución temporal del corpus (331 artículos WoS)", labels={"Año": "Año de publicación", "Artículos": "N artículos"}, text="Artículos", height=420,)fig.update_traces(marker_color="#1f77b4", textposition="outside")fig.update_layout(xaxis={"dtick": 1})fig.show()```## Top 10 revistas```{python}#| label: top-journals#| fig-cap: "Revistas con mayor número de artículos en el corpus"import pandas as pdjournal_col ="Source Title"if"Source Title"in df.columns else"Journal"if journal_col in df.columns: top_journals = ( df[journal_col] .dropna() .value_counts() .head(10) .reset_index() ) top_journals.columns = ["Revista", "Artículos"] fig2 = px.bar( top_journals, x="Artículos", y="Revista", orientation="h", title="Top 10 revistas por número de artículos", labels={"Artículos": "N artículos", "Revista": ""}, text="Artículos", height=420, ) fig2.update_layout(yaxis={"categoryorder": "total ascending"}) fig2.update_traces(marker_color="#ff7f0e", textposition="outside") fig2.show()else:print("Columna de revista no encontrada. Columnas disponibles:", list(df.columns[:10]))```## Tabla interactiva de revistas```{python}#| label: journals-tabletry:from itables import showif journal_col in df.columns: journals_full = ( df[journal_col] .dropna() .value_counts() .reset_index() ) journals_full.columns = ["Revista", "Artículos"] show( journals_full, caption="Revistas en el corpus (todas)", lengthMenu=[10, 25, 50], scrollY="400px", )exceptImportError:print("itables no disponible. Instalar con: pip install itables")if journal_col in df.columns: display( df[journal_col] .dropna() .value_counts() .head(20) .to_frame("Artículos") )```## Cobertura de keywords```{python}#| label: keyword-coverageak_col ="Author Keywords"kp_col ="Keywords Plus"has_ak = df[ak_col].notna().sum() if ak_col in df.columns else0has_kp = df[kp_col].notna().sum() if kp_col in df.columns else0has_both = ( (df[ak_col].notna() & df[kp_col].notna()).sum()if ak_col in df.columns and kp_col in df.columnselse0)has_none =len(df) - (df[ak_col].notna() | df[kp_col].notna()).sum() if ak_col in df.columns and kp_col in df.columns else"N/A"print(f"Artículos con Author Keywords : {has_ak} ({100*has_ak/len(df):.1f}%)")print(f"Artículos con Keywords Plus : {has_kp} ({100*has_kp/len(df):.1f}%)")print(f"Artículos con ambas : {has_both} ({100*has_both/len(df):.1f}%)")print(f"Artículos sin ninguna : {has_none}")```::: {.callout-note}La estrategia de preprocesamiento usa **Author Keywords** como fuente primaria y complementacon **Keywords Plus** únicamente para los artículos que carecen de keywords de autor.Esto maximiza la cobertura sin duplicar información.:::