Análisis de patentes

Una patente es un conjunto de derechos exclusivos concedidos por un Estado al inventor de un nuevo producto o tecnología, susceptibles de ser explotados comercialmente por un período limitado de tiempo, a cambio de la divulgación de la invención.

En un mundo globalizado, donde el éxito de desarrollos tecnológicos depende significativamente de la colaboración de los distintos actores, analizar los datos de las patentes tiene un potencial inexplorado. Las herramientas para realizar distintos analisis de la información disponible permite mejorar la toma de decisiones a todo tipo de organizaciones.

El número de patentes aprobadas en el mundo crece rapidamente cada año, por lo que se requieren análisis de patentes que extraigan efectivamente la información valiosa contenida en ellas.

PatentScope es la base de datos pública de WIPO. Incluye la cobertura de las solicitudes del Tratado de Cooperación en materia de Patentes (administradas por WIPO) y una amplia gama de otros países, incluida la Oficina Europea de Patentes, la USPTO y Japón. Actualmente la base cuenta con más de 97 millones de documentos de patentes.

Para este análisis de patentes se utilizará una base descargada desde PatentScope. La base es el resultado de la búsqueda “FP:(irrigation) AND (analysis) AND (humidity)” con 434 resultados.

rm(list=ls())               # Limpiamos todos los objetos creados en R
graphics.off()              # Limpiamos los gráficos
options(digits = 3)         # Declaramos dígitos despues del punto para observar (decimas, centesimas,...)
set.seed(12345) #fijar semilla de aleatoriedad
setwd("/cloud/project") #fijar directorio de preferencia

Configuraciones iniciales

Primero se carga la base tal como se descargo desde el sitio.

library(readxl)
BD <- read_excel("/cloud/project/Instasoil/busqueda 1.xls",  skip = 5) #cargar datos
head(BD)

Se gráfican los missing values.

library(visdat)
vis_miss(BD)

Se realizan algunas modificaciones para los posteriores análisis:

library(dplyr)
library(stringr)
library(lubridate)

Las columnas con fechas con el formato correcto.

BD <- BD %>%
  mutate(`Publication Date` = as.Date(`Publication Date`, "%d.%m.%Y" ) ,
         `Application Date` = as.Date(`Application Date`, "%d.%m.%Y" ) )

Para el analisis se filtan las patentes desde el año 2000 según el año de publicación, el cual no tiene missing values. En este paso la base resultante es de 406 filas (patentes).

BD <- BD %>%
  filter(`Publication Date` > "1999-12-31") %>%
  arrange(desc(`Publication Date`)) 

Las columnas con textos se pasan a minusculas para evitar futuras incongruencias. Además se separa la columna con los solictantes, para obtener una columna con el primero.

library(stringr)
library(tidyr)
BD <- BD %>%
  mutate(Title = str_trim(tolower(Title), side = "both"), 
         Abstract =str_trim(tolower(Abstract), side = "both"), 
         Applicants = str_trim(tolower(Applicants), side = "both"),
         Inventors = str_trim(tolower(Inventors), side = "both") ) %>%  
  separate(Applicants, c("first_Applicant", "rest_Applicants"),"; ",fill = "right", extra = "merge") %>%
  mutate(first_Applicant = str_trim(first_Applicant, side = "both"))

Dado que los analisis se realizarán con los Abstract de los documentos, se filtran aquellos sin esta variable.

BD <- BD %>%
  filter(!is.na(Abstract))

Dado que los inventos se patentan en más de un país, se crea otra data sin duplicados con 286 filas.

BD_unq <- BD %>%
  distinct(Title, .keep_all= TRUE)

Exploración inicial

A continuacíón se muestran gráficos que permiten caracterizar la base a analizar.

Por país de la patente

library(ggplot2)
library(gridExtra)
## 
## Attaching package: 'gridExtra'
## The following object is masked from 'package:dplyr':
## 
##     combine
plot1 <- ggplot(BD, aes(x= Country)) + geom_bar()+
  labs(title="Patentes por paises", x="Paises", y="Frecuencia") + ylim(0, 165)
plot2 <- ggplot(BD_unq, aes(x= Country)) + geom_bar()+
  labs(title="Patentes por paises en base sin duplicados", x="Paises", y="Frecuencia") + ylim(0, 165)

do.call("grid.arrange", c(list(plot1, plot2), ncol = 2)) 

library(maps)
library(RColorBrewer)
library(forcats)

b=data.frame(table(BD$Country))
colnames(b)=c("Country","count")
b$count_group <- cut(b$count, 
                       breaks = c(-Inf, 5, 10, 25, 50, Inf), 
                       labels = c("Less than 5", "6-10", "11-25", "26-50", "More than 51"))
 
world_map <- map_data(map = "world")
world_map$region <- iso.alpha(world_map$region)

plot1=ggplot(b) +
  geom_map(aes(map_id = Country, fill = fct_rev(count_group)), map = world_map) +
  geom_polygon(data = world_map, aes(x = long, y = lat, group = group), colour = 'black', fill = NA) +
  expand_limits(x = world_map$long, y = world_map$lat) +
  scale_fill_manual(name = "Counts", values = rev(brewer.pal(5, name = "Reds"))) +
  theme_void() +
  coord_fixed()+
  labs(title="Patentes por paises")

b=data.frame(table(BD_unq$Country))
colnames(b)=c("Country","count")
b$count_group <- cut(b$count, 
                       breaks = c(-Inf, 5, 10, 25, 50, Inf), 
                       labels = c("Less than 5", "6-10", "11-25", "26-50", "More than 51"))

plot2=ggplot(b) +
  geom_map(aes(map_id = Country, fill = fct_rev(count_group)), map = world_map) +
  geom_polygon(data = world_map, aes(x = long, y = lat, group = group), colour = 'black', fill = NA) +
  expand_limits(x = world_map$long, y = world_map$lat) +
  scale_fill_manual(name = "Counts", values = rev(brewer.pal(5, name = "Reds"))) +
  theme_void() +
  coord_fixed()+
  labs(title="Patentes por paises en base sin duplicados")

do.call("grid.arrange", c(list(plot1, plot2), ncol = 1)) 

Por año de pubicación de la patente

plot1 <- ggplot(BD, aes(x= year(`Publication Date`))) + geom_bar()+
  labs(title="Patentes por año", x="Año de publicación", y="Frecuencia") + ylim(0, 70)
plot2 <- ggplot(BD_unq, aes(x= year(`Publication Date`))) + geom_bar()+
  labs(title="Patentes por año en base sin duplicados", x= "Año de publicación", y="Frecuencia") + ylim(0, 70)

do.call("grid.arrange", c(list(plot1, plot2), ncol = 2) )

plot1 <- ggplot(BD, aes(x= year(`Publication Date`),fill=Country)) + geom_bar()+
  labs(title="Patentes por año", x="Año de publicación", y="Frecuencia") + ylim(0, 70)
plot2 <- ggplot(BD_unq, aes(x= year(`Publication Date`), fill= Country)) + geom_bar()+
  labs(title="Patentes por año en base sin duplicados", x= "Año de publicación", y="Frecuencia") + ylim(0, 70)

do.call("grid.arrange", c(list(plot1, plot2), ncol = 2) )

#### Palabras más presentes en las patentes

En esta parte solo se usa la base sin títulos duplicados.

BD_text <- tibble(APPLICATION = BD_unq$`Application Id` , ABSTRACT = BD_unq$Abstract, TITLE= BD_unq$Title)

library(tidytext)
data(stop_words)

plot1 = BD_text %>%
  unnest_tokens(word, ABSTRACT) %>%
  anti_join(stop_words) %>%
  count(word, sort = TRUE) %>%
  #filter(n > 100 & word > "a") %>%
  mutate(word = reorder(word, n)) %>%
  slice_head(n = 25) %>%
  ggplot(aes(n, word)) +
  geom_col() +
  labs(title= "Top Abstracts words", y=NULL, x= "Frecuencia")
## Joining, by = "word"
plot2 = BD_text %>%
  unnest_tokens(word, TITLE) %>%
  anti_join(stop_words) %>%
  count(word, sort = TRUE) %>%
  #filter(n > 10 & word > "a") %>%
  mutate(word = reorder(word, n)) %>%
  slice_head(n = 25) %>%
  ggplot(aes(n, word)) +
  geom_col() + 
  labs(title= "Top Title words", y=NULL, x= "Frecuencia")
## Joining, by = "word"
do.call("grid.arrange", c(list(plot1, plot2), ncol = 2)) 

Por solicitante de la patente

plot1 = BD %>%
  count(first_Applicant, sort = TRUE) %>%
  #filter(n > 100 & word > "a") %>%
  mutate(first_Applicant= reorder(first_Applicant, n)) %>%
  slice_head(n = 12) %>%
  ggplot(aes(n, first_Applicant)) +
  geom_col() +
  labs(title= "Solicitantes", y=NULL, x= "Frecuencia")+
  xlim(0,18)

plot2 = BD_unq %>%
  count(first_Applicant, sort = TRUE) %>%
  #filter(n > 100 & word > "a") %>%
  mutate(first_Applicant= reorder(first_Applicant, n)) %>%
  slice_head(n = 12) %>%
  ggplot(aes(n, first_Applicant)) +
  geom_col() +
  labs(title= "Solicitantes en base sin duplicados", y=NULL, x= "Frecuencia")+
  xlim(0,18)


do.call("grid.arrange", c(list(plot1, plot2), ncol = 1)) 

save(BD, file = "BD.RData")
save(BD_unq, file = "BD_unq.RData")