Skip to content

Nicolas-Schmidt/speech-ejemplos

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ejemplos y usos del paquete speech 📃

Nicolás Schmidt, Elina Gómez

visitors

Índice

Descripción

El paquete speech permite convertir diarios de sesión del parlamento uruguayo en formato PDF a bases de datos ordenadas en la que cada fila es la intervención de cada uno de los legisladores que interviene en esa sesión. Asimismo, dado que los diarios de sesión muchas veces son imágenes escaneadas y que en el proceso de OCR (reconocimiento óptico de caracteres por su sigla en inglés) se puede perder o dañar la información recuperada, el paquete provee un conjunto de funciones que ayudan a mejorar problemas de este tipo.

Características

Este paquete ordena todas las intervenciones por sesión de cada uno de los legisladores. Esto quiere decir que todas las intervenciones de los presidentes, secretarios, ministros o personas invitadas no identificadas como legisladores no van a ser recuperadas por el algoritmo de recuperación del texto del PDF. Muchas veces puede suceder que el algoritmo no identifique claramente alguna de estas intervenciones (que se identifican y se eliminan). En esos casos la función con la que se pasa de un archivo con extensión .pdf a un data.frame (speech_build()) tiene un argumento (rm.error.leg) que permite incorporar esos casos que se desean eliminar y no fueron identificados por la función.

Algo similar puede suceder con los legisladores. Una opción es que se use la función y que cada fila de la base de datos sea cada una de las intervenciones de cada legislador en cada momento. Esto quiere decir que se va a tener tantas intervenciones por legislador como cuantas intervenciones haya realizado en esa sesión. La otra opción (usando speech_build(., compiler = TRUE) o speech_recompiler()) es que cada fila de la base de datos sen todas las intervenciones juntas en una misma sesión de cada legislador o legisladora. El problema que puede surgir en con esta opción es que la unión de intervenciones se hace por legislador y si en el proceso de recuperación del texto el nombre de algún legislador no aparece escrito correctamente la compilación no va a reconocer a ese legislador que es el mismo, pero está escrito de distintas maneras. Para solucionar estos problemas y poder compilar el paquete tiene una función que permite arreglar este problema: speech_legis_replace().

Ejemplos

Es importante tener presente que la lectura del texto de los archivos PDF de los diarios de sesión no es siempre clara. Muchos de los diarios de sesión que están en la página web del parlamento están escaneados.

En algunas ocasiones antes de convertir el documento PDF que contiene un diario de sesión mediante el uso de la función speech_build() va a ser necesario pasar el PDF por un OCR (reconocimiento óptico de caracteres por su sigla en inglés).

Lo primero que hay que hacer en caso de no tener instalado el paquete es instalarlo. En la web del paquete debe verificar cual es la última versión. Si el número de versión de CRAN coincide con la de GitHub instale la de CRAN caso contrario instale la versión de GitHub. Esto lo puede verificar en las etiquetas (badges) que aparecen abajo a la derecha en la web del paquete.

Versión de CRAN:

install.packages("speech")

Versión de GitHub:

if (!require("remotes")) install.packages("remotes")
remotes::install_github("Nicolas-Schmidt/speech")

Una vez instalado el paquete debe cargarlo en la sesión de trabajo:

library(speech)
#> Warning: package 'speech' was built under R version 4.1.3

Vamos a ver 4 ejemplos que presentan distintos problemas y niveles de complejidad en su procesamiento:

  • El diario de sesión de la Asamblea General de la reapertura democrática: 15 de febrero de 1985.
  • Un diario de sesión sobre la creación de los consejos de salarios del 13 de octubre de 1941.
  • Un diario de sesión reciente de una sesión convencional de la Comisión Permanente del 17 de setiembre de 2019.
  • Descarga masiva de sesiones correspondiente a un período de tiempo detarminado.

Ejemplo 1

▶️ El primer diario de sesión de la Asamblea General desde la reapertura democrática: 15 de febrero de 1985.

Lo primero que vamos a hacer es buscar la url al diario de sesión con el que queremos trabajar o los descargamos en el argumento file ponemos el nombre del archivo pdf con el que lo guardamos. Hecho eso vamos directo a la función principal que es por donde se empieza. Vamos a usarla sin el argumento compiler para detectar posibles problemas como los comentados en la sección anterior.

url <- "https://parlamento.gub.uy/documentosyleyes/documentos/diario-de-sesion/asambleageneral/1/IMG/0?width=800&height=600&hl=en_US1&iframe=true&rel=nofollow"

text <- speech::speech_build(file = url)

print(text, n = nrow(text))
#> # A tibble: 28 x 7
#>    legislator        speech           chamber date       legislature id      sex
#>    <chr>             <chr>            <chr>   <date>           <int> <chr> <dbl>
#>  1 PEREYRA           "SEÑOR PER. EYR~ ASAMBL~ 1985-02-15          42 0?wi~     1
#>  2 CORDOSO           "SEÑOR CORDOSO.~ ASAMBL~ 1985-02-15          42 0?wi~     1
#>  3 ROSSI PASSINA     "SEÑOR ROSSI PA~ ASAMBL~ 1985-02-15          42 0?wi~     1
#>  4 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#>  5 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#>  6 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#>  7 FERREIRA          "SEÑOR FERREIRA~ ASAMBL~ 1985-02-15          42 0?wi~     1
#>  8 FElRREIRA Señ     "SEÑOR FElRREIR~ ASAMBL~ 1985-02-15          42 0?wi~     1
#>  9 RODRIGUEZ CAMUSSO "SEÑOR RODRIGUE~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 10 RODRIGUEZ CAMUSSO "SEÑOR RODRIGUE~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 11 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 12 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 13 PAZ AGUIRRE       "SEÑOR PAZ AGUI~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 14 PAZ AG            "SEÑOR PAZ AGUr~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 15 CIGLIUTI          "SEÑOR CIGLIUTI~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 16 CIGLIUTI          "SEÑOR CIGLIUTI~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 17 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 18 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 19 PIRIESIDENTE      "SEÑOR PIRIESID~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 20 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 21 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 22 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 23 PAZ AGUIRRE       "SEÑOR PAZ AGUI~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 24 PAZ AGUIRRE       "SEÑOR PAZ AGUI~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 25 VAILLANT          "SEÑOR VAILLANT~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 26 VAILLANT          "SEÑOR VAILLANT~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 27 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 28 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1

Si bien la base de datos llamada text luce bien (hay legisladores, se reconoció la cámara, la fecha…) se aprecian varios problemas que son producto de la lectura del documento. Este documento está escaneado y hay caracteres que no se leen correctamente: por ejemplo, legislador 7 y 8 parecen ser el mismo, pero al compilar los datos no se van a juntar ya que no están escritos igual; el legislador 25 y 26 es el mismo solo que en el primer caso hay un espacio en medio del apellido de uno de los legisladores. El legislador 13, 23 y 24 parecen ser el mismo que el 14.

También se aprecia que hay un ‘legislador’ que no es legislador y que no debería aparecer: el 19: ‘PIRIESIDENTE’.

Comencemos por el ultimo problema. La función speech_build() tiene un argumento que permite eliminar ‘legisladores’ que no queremos en nuestra base de datos: rm.error.leg

text <- speech::speech_build(file = url, rm.error.leg = "PIRIESIDENTE")

## verificamos que ya no esté

print(text, n = nrow(text))
#> # A tibble: 27 x 7
#>    legislator        speech           chamber date       legislature id      sex
#>    <chr>             <chr>            <chr>   <date>           <int> <chr> <dbl>
#>  1 PEREYRA           "SEÑOR PER. EYR~ ASAMBL~ 1985-02-15          42 0?wi~     1
#>  2 CORDOSO           "SEÑOR CORDOSO.~ ASAMBL~ 1985-02-15          42 0?wi~     1
#>  3 ROSSI PASSINA     "SEÑOR ROSSI PA~ ASAMBL~ 1985-02-15          42 0?wi~     1
#>  4 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#>  5 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#>  6 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#>  7 FERREIRA          "SEÑOR FERREIRA~ ASAMBL~ 1985-02-15          42 0?wi~     1
#>  8 FElRREIRA Señ     "SEÑOR FElRREIR~ ASAMBL~ 1985-02-15          42 0?wi~     1
#>  9 RODRIGUEZ CAMUSSO "SEÑOR RODRIGUE~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 10 RODRIGUEZ CAMUSSO "SEÑOR RODRIGUE~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 11 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 12 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 13 PAZ AGUIRRE       "SEÑOR PAZ AGUI~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 14 PAZ AG            "SEÑOR PAZ AGUr~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 15 CIGLIUTI          "SEÑOR CIGLIUTI~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 16 CIGLIUTI          "SEÑOR CIGLIUTI~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 17 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 18 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 19 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 20 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 21 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 22 PAZ AGUIRRE       "SEÑOR PAZ AGUI~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 23 PAZ AGUIRRE       "SEÑOR PAZ AGUI~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 24 VAILLANT          "SEÑOR VAILLANT~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 25 VAILLANT          "SEÑOR VAILLANT~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 26 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1
#> 27 TOURNE            "SEÑOR TOURNE. ~ ASAMBL~ 1985-02-15          42 0?wi~     1

Como se puede ver en la nueva base de datos text ya no aparece la fila 19 con los datos anteriores.

Ahora deberíamos solucionar el problema de los nombres de los legisladores que si queremos que permanezcan en nuestra base de datos y que debemos corregir para poder compilarlos correctamente.

El paquete speech tiene una función que permite chequear los nombres de los legisladores (speech_check()) y otra fundción que permite modificar fácilmente los nombres de los legisladores: speech_legis_replace.

Vamos a chequear los nombres:

speech::speech_check(text)
#> $C
#>   legislator
#> 1   CIGLIUTI
#> 2    CORDOSO
#> 
#> $F
#>      legislator
#> 1 FElRREIRA Señ
#> 2      FERREIRA
#> 
#> $P
#>    legislator
#> 1      PAZ AG
#> 2 PAZ AGUIRRE
#> 3     PEREYRA
#> 
#> $R
#>          legislator
#> 1 RODRIGUEZ CAMUSSO
#> 2     ROSSI PASSINA
#> 
#> $T
#>   legislator
#> 1     TOURNE
#> 
#> $V
#>   legislator
#> 1   VAILLANT

La función speech_check() devuelve una lista de nombres ordenados por inicial. Esta función permite visualizar los problemas de un modo más amigable y fácil. Lo que se puede apreciar es que hay distintos tipos de errores: en los legisladores que inicial con F, con P y con V.

Ahora vamos a cambiar los nombres que están mal:

text <- speech::speech_legis_replace(text, old = "FElRREIRA Señ",  new = "FERREIRA")
text <- speech::speech_legis_replace(text, old = "V AILLANT",  new = "VAILLANT")
text <- speech::speech_legis_replace(text, old = "PAZ AG",  new = "PAZ AGUIRRE")
text <- speech::speech_legis_replace(text, old = "CORDOSO",  new = "CARDOSO")

Con esta función lo que hacemos es modificar la base construida (es decir el objeto text) por eso debemos sobrescribirla.

Ahora debemos chequear que los cambios se realizaron de manera correcta:

speech::speech_check(text)
#> $C
#>   legislator
#> 1    CARDOSO
#> 2   CIGLIUTI
#> 
#> $F
#>   legislator
#> 1   FERREIRA
#> 
#> $P
#>    legislator
#> 1 PAZ AGUIRRE
#> 2     PEREYRA
#> 
#> $R
#>          legislator
#> 1 RODRIGUEZ CAMUSSO
#> 2     ROSSI PASSINA
#> 
#> $T
#>   legislator
#> 1     TOURNE
#> 
#> $V
#>   legislator
#> 1   VAILLANT

Una vez que consideramos que ya no hay más cambios por realizar podemos recompilar el diario de sesión. Tenemos que recompilarlo ya que hemos modificado la compilación inicial.

text2 <- speech::speech_recompiler(tidy_speech = text)
print(text2, n = nrow(text2))
#> # A tibble: 9 x 7
#>   legislator        legislature chamber          date       id        sex speech
#>   <chr>                   <int> <chr>            <date>     <chr>   <dbl> <chr> 
#> 1 CARDOSO                    42 ASAMBLEA GENERAL 1985-02-15 0?widt~     1 "SEÑO~
#> 2 CIGLIUTI                   42 ASAMBLEA GENERAL 1985-02-15 0?widt~     1 "SEÑO~
#> 3 FERREIRA                   42 ASAMBLEA GENERAL 1985-02-15 0?widt~     1 "SEÑO~
#> 4 PAZ AGUIRRE                42 ASAMBLEA GENERAL 1985-02-15 0?widt~     1 "SEÑO~
#> 5 PEREYRA                    42 ASAMBLEA GENERAL 1985-02-15 0?widt~     1 "SEÑO~
#> 6 RODRIGUEZ CAMUSSO          42 ASAMBLEA GENERAL 1985-02-15 0?widt~     1 "SEÑO~
#> 7 ROSSI PASSINA              42 ASAMBLEA GENERAL 1985-02-15 0?widt~     1 "SEÑO~
#> 8 TOURNE                     42 ASAMBLEA GENERAL 1985-02-15 0?widt~     1 "SEÑO~
#> 9 VAILLANT                   42 ASAMBLEA GENERAL 1985-02-15 0?widt~     1 "SEÑO~

Una vez que tenemos la base final (text2) ahora podemos proceder a usar el paquete puy (:boom::exclamation:) que permite agregar la etiqueta partidaria y el nombre completo de cada legislador.

library(puy)

datos <- add_party(text2)
datos
#> # A tibble: 9 x 12
#>   legislator legislature chamber date       id    speech   sex legislator2 party
#>   <chr>            <int> <chr>   <date>     <chr> <chr>  <dbl> <chr>       <chr>
#> 1 CARDOSO             42 ASAMBL~ 1985-02-15 0?wi~ "SEÑO~     1 CARDOSO, J~ Fren~
#> 2 CIGLIUTI            42 ASAMBL~ 1985-02-15 0?wi~ "SEÑO~     1 CIGLIUTI, ~ Part~
#> 3 FERREIRA            42 ASAMBL~ 1985-02-15 0?wi~ "SEÑO~     1 FERREIRA, ~ Part~
#> 4 PAZ AGUIR~          42 ASAMBL~ 1985-02-15 0?wi~ "SEÑO~     1 PAZ AGUIRR~ Part~
#> 5 PEREYRA             42 ASAMBL~ 1985-02-15 0?wi~ "SEÑO~     1 PEREYRA, C~ Part~
#> 6 RODRIGUEZ~          42 ASAMBL~ 1985-02-15 0?wi~ "SEÑO~     1 RODRIGUEZ ~ Fren~
#> 7 ROSSI PAS~          42 ASAMBL~ 1985-02-15 0?wi~ "SEÑO~     1 ROSSI PASS~ Unio~
#> 8 TOURNE              42 ASAMBL~ 1985-02-15 0?wi~ "SEÑO~     1 TOURNE, Ur~ Part~
#> 9 VAILLANT            42 ASAMBL~ 1985-02-15 0?wi~ "SEÑO~     1 VAILLANT, ~ Part~
#> # ... with 3 more variables: party_acron <chr>, indicator <int>, words <dbl>

Ejemplo 2

▶️ Un diario de sesión sobre la creación de los consejos de salarios del 13 de octubre de 1941.
text <- speech::speech_build(file = "speech_example.pdf")
print(text)
#> # A tibble: 123 x 7
#>    legislator   speech                chamber date   legislature id          sex
#>    <chr>        <chr>                 <chr>   <date>       <int> <chr>     <dbl>
#>  1 ITURBIDE     "SEÑOR ITURBIDE. — H~ <NA>    NA              NA speech_e~     1
#>  2 DAMBORIARENA "SEÑOR DAMBORIARENA.~ <NA>    NA              NA speech_e~     1
#>  3 MOREIRA      "SEÑOR MOREIRA. — Se~ <NA>    NA              NA speech_e~     1
#>  4 GOMEZ        "SEÑOR GOMEZ. — Se h~ <NA>    NA              NA speech_e~     1
#>  5 BRUNO        "SEÑOR BRUNO, — Seño~ <NA>    NA              NA speech_e~     1
#>  6 CERSOSIMO    "SEÑOR CERSOSIMO. — ~ <NA>    NA              NA speech_e~     1
#>  7 PUIG         "SEÑOR PUIG. — Señor~ <NA>    NA              NA speech_e~     1
#>  8 SALGADO      "SEÑOR SALGADO. — Pi~ <NA>    NA              NA speech_e~     1
#>  9 SALGADO      "SEÑOR SALGADO. ~ Te~ <NA>    NA              NA speech_e~     1
#> 10 SALGADO      "SEÑOR SALGADO. — Ya~ <NA>    NA              NA speech_e~     1
#> # ... with 113 more rows

Lo primero que vemos es que aparecen errores en nombres, la variable cámara, fecha y legislatura no fueron identificadas. Esto nos da la pauta de que el documento no es de muy buena calidad. Vamos a chequear los nombres de los legisladores previo a compilar:

speech::speech_check(text)
#> $A
#>   legislator
#> 1    ANTUNEZ
#> 2  ARISMENDI
#> 3  ARISMENDT
#> 
#> $B
#>                 legislator
#> 1                    BKANE
#> 2                    BREÑA
#> 3 BRUNEREAU DES HOUILLERES
#> 4                    BRUNO
#> 5               BTJRANELLI
#> 6                 BURANELL
#> 7                BURANELLI
#> 
#> $C
#>      legislator
#> 1 CAl l e r IZA
#> 2     CALLERIZA
#> 3     CALLERTZA
#> 4       CARDOSO
#> 5     CAUTERIZA
#> 6     CERSOSIMO
#> 7     CERSOSTMO
#> 8 CHOTJHY TERRA
#> 9  CHOUHY TERRA
#> 
#> $D
#>     legislator
#> 1 DAMBORIARENA
#> 
#> $E
#>   legislator
#> 1   ESPALTER
#> 
#> $F
#>         legislator
#> 1 FERNANDEZ CRESPO
#> 
#> $G
#>   legislator
#> 1     GARLON
#> 2     GARZON
#> 3      GOMEZ
#> 4   GONZALEZ
#> 
#> $I
#>   legislator
#> 1   ITURBIDE
#> 
#> $J
#>   legislator
#> 1 JUiHANELLl
#> 
#> $M
#>        legislator
#> 1        MARTINEZ
#> 2     miRBTDE Pid
#> 3         MOREIRA
#> 4 MORENO ZEBALLOS
#> 
#> $O
#>   legislator
#> 1        OIS
#> 2      OLEHO
#> 3      OTERO
#> 
#> $P
#>            legislator
#> 1 P R E S I D E N T E
#> 2          PRENOTENTE
#> 3         PRPJSIDENTE
#> 4          PUaU tSiio
#> 5                PUIG
#> 6                PUTG
#> 
#> $R
#>            legislator
#> 1                  RO
#> 2     RODRIGLEZ ROCHA
#> 3 RODRIGUEZ R O C H A
#> 4     RODRIGUEZ ROCHA
#> 5                 ROT
#> 
#> $S
#>   legislator
#> 1    SALGADO
#> 2       SEÑO
#> 
#> $T
#>   legislator
#> 1    TIJBINO
#> 2      TROIT
#> 3   TROITIÑO
#> 4   TTERBIDE
#> 5    TTJBINO
#> 6     TUBINO
#> 7     TURINO

Vemos que hay errores de dos tipos. El primero es de presidentes que no han sido eliminados, y el segundo es que muchos nombres de los legisladores están mal escritos. Esto se debe exclusivamente a la mala calidad del OCR que tiene este documento. Sin embargo, como vamos a ver el paquete text2 proporciona las funciones adecuadas para lidiar con este tipo de problemas. Vamos a comenzar eliminado a los presidentes.

text <- speech::speech_build(file = "speech_example.pdf", 
                             rm.error.leg = c("P R E S ID E N T E", 
                                              "PRPJSIDENTE", 
                                              "PRPJSIDENTE", 
                                              "PRENOTENTE"))
speech::speech_check(text)
#> $A
#>   legislator
#> 1    ANTUNEZ
#> 2  ARISMENDI
#> 3  ARISMENDT
#> 
#> $B
#>                 legislator
#> 1                    BKANE
#> 2                    BREÑA
#> 3 BRUNEREAU DES HOUILLERES
#> 4                    BRUNO
#> 5               BTJRANELLI
#> 6                 BURANELL
#> 7                BURANELLI
#> 
#> $C
#>      legislator
#> 1 CAl l e r IZA
#> 2     CALLERIZA
#> 3     CALLERTZA
#> 4       CARDOSO
#> 5     CAUTERIZA
#> 6     CERSOSIMO
#> 7     CERSOSTMO
#> 8 CHOTJHY TERRA
#> 9  CHOUHY TERRA
#> 
#> $D
#>     legislator
#> 1 DAMBORIARENA
#> 
#> $E
#>   legislator
#> 1   ESPALTER
#> 
#> $F
#>         legislator
#> 1 FERNANDEZ CRESPO
#> 
#> $G
#>   legislator
#> 1     GARLON
#> 2     GARZON
#> 3      GOMEZ
#> 4   GONZALEZ
#> 
#> $I
#>   legislator
#> 1   ITURBIDE
#> 
#> $J
#>   legislator
#> 1 JUiHANELLl
#> 
#> $M
#>        legislator
#> 1        MARTINEZ
#> 2     miRBTDE Pid
#> 3         MOREIRA
#> 4 MORENO ZEBALLOS
#> 
#> $O
#>   legislator
#> 1        OIS
#> 2      OLEHO
#> 3      OTERO
#> 
#> $P
#>            legislator
#> 1 P R E S I D E N T E
#> 2          PUaU tSiio
#> 3                PUIG
#> 4                PUTG
#> 
#> $R
#>            legislator
#> 1                  RO
#> 2     RODRIGLEZ ROCHA
#> 3 RODRIGUEZ R O C H A
#> 4     RODRIGUEZ ROCHA
#> 5                 ROT
#> 
#> $S
#>   legislator
#> 1    SALGADO
#> 2       SEÑO
#> 
#> $T
#>   legislator
#> 1    TIJBINO
#> 2      TROIT
#> 3   TROITIÑO
#> 4   TTERBIDE
#> 5    TTJBINO
#> 6     TUBINO
#> 7     TURINO

Solucionado este problema ahora pasamos al problema de los nombres de los legisladores que son varios:

text <- speech_legis_replace(text, old = "ARISMENDT",     new = "ARISMENDI")
text <- speech_legis_replace(text, old = "BURANELL",      new = "BURANELLI")
text <- speech_legis_replace(text, old = "BTJRANELLI",    new = "BURANELLI")
text <- speech_legis_replace(text, old = "JUiHANELLl",    new = "BURANELLI")
text <- speech_legis_replace(text, old = "BKANE",         new = "BURANELLI")
text <- speech_legis_replace(text, old = "CAl l e r IZA", new = "CALLERIZA")
text <- speech_legis_replace(text, old = "CALLERTZA",     new = "CALLERIZA")
text <- speech_legis_replace(text, old = "CAUTERIZA",     new = "CALLERIZA")
text <- speech_legis_replace(text, old = "CERSOSTMO",     new = "CERSOSIMO")
text <- speech_legis_replace(text, old = "CHOTJHY TERRA", new = "CHOUHY TERRA")
text <- speech_legis_replace(text, old = "GARLON",        new = "GARZON")
text <- speech_legis_replace(text, old = "PUTG",          new = "PUIG")
text <- speech_legis_replace(text, old = "PUaU tSiio",    new = "PUIG")
text <- speech_legis_replace(text, old = "FUJLG",         new = "PUIG")
text <- speech_legis_replace(text, old = "TIJBINO",       new = "TUBINO")
text <- speech_legis_replace(text, old = "TTJBINO",       new = "TUBINO")
text <- speech_legis_replace(text, old = "TTTBTNO",       new = "TUBINO")
text <- speech_legis_replace(text, old = "TURINO",        new = "TUBINO")
text <- speech_legis_replace(text, old = "TTERBIDE",      new = "ITURBIDE")
text <- speech_legis_replace(text, old = "miRBTDE Pid",   new = "ITURBIDE")
text <- speech_legis_replace(text, old = "TROIT",         new = "TROITIÑO")
text <- speech_legis_replace(text, old = "MORENO ERADLOS",new = "MORENO ZEBALLOS")
text <- speech_legis_replace(text, old = "MORENO RALLOS", new = "MORENO ZEBALLOS")
text <- speech_legis_replace(text, old = "OLEHO",         new = "OTERO")
text <- speech_legis_replace(text, old = "RO",            new = "RODRIGUEZ ROCHA")
text <- speech_legis_replace(text, old = "BREÑA",         new = "BRENA")
text <- speech_legis_replace(text, old = "RODRIGUEZ R O C H A",       new = "RODRIGUEZ ROCHA")
text <- speech_legis_replace(text, old = "RODRIGLEZ ROCHA",           new = "RODRIGUEZ ROCHA")
text <- speech_legis_replace(text, old = "ROT",                       new = "RODRIGUEZ ROCHA")
text <- speech_legis_replace(text, old = "BRUNEREAU DES HOUILLERES",  new = "BRUNERAU DES HOUILLERES")


speech_check(text)
#> $A
#>   legislator
#> 1    ANTUNEZ
#> 2  ARISMENDI
#> 
#> $B
#>                legislator
#> 1                   BRENA
#> 2 BRUNERAU DES HOUILLERES
#> 3                   BRUNO
#> 4               BURANELLI
#> 
#> $C
#>     legislator
#> 1    CALLERIZA
#> 2      CARDOSO
#> 3    CERSOSIMO
#> 4 CHOUHY TERRA
#> 
#> $D
#>     legislator
#> 1 DAMBORIARENA
#> 
#> $E
#>   legislator
#> 1   ESPALTER
#> 
#> $F
#>         legislator
#> 1 FERNANDEZ CRESPO
#> 
#> $G
#>   legislator
#> 1     GARZON
#> 2      GOMEZ
#> 3   GONZALEZ
#> 
#> $I
#>   legislator
#> 1   ITURBIDE
#> 
#> $M
#>        legislator
#> 1        MARTINEZ
#> 2         MOREIRA
#> 3 MORENO ZEBALLOS
#> 
#> $O
#>   legislator
#> 1        OIS
#> 2      OTERO
#> 
#> $P
#>            legislator
#> 1 P R E S I D E N T E
#> 2                PUIG
#> 
#> $R
#>        legislator
#> 1 RODRIGUEZ ROCHA
#> 
#> $S
#>   legislator
#> 1    SALGADO
#> 2       SEÑO
#> 
#> $T
#>   legislator
#> 1   TROITIÑO
#> 2     TUBINO

Como podemos ver fueron varias las correcciones que se hicieron. Pero al volver a chequear podemos verificar que la base de datos luce perfectamente limpia. Previo a compilar es necesario cargar los datos faltantes de dos variables claves: la legislatura (legislature) y la cámara (chamber). Luego podemos pasar a compilar el diario de sesión.

text$legislature <- 33
text$chamber     <- "CAMARA DE REPRESENTANTES"


text2 <- speech_recompiler(text)
#> Warning: Variables that are in 'compiler_by' contain NA values: date
print(text2, n = Inf)
#> # A tibble: 29 x 7
#>    legislator              legislature chamber     date   id          sex speech
#>    <chr>                         <int> <chr>       <date> <chr>     <dbl> <chr> 
#>  1 ANTUNEZ                          33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#>  2 ARISMENDI                        33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#>  3 BRENA                            33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#>  4 BRUNERAU DES HOUILLERES          33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#>  5 BRUNO                            33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#>  6 BURANELLI                        33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#>  7 CALLERIZA                        33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#>  8 CARDOSO                          33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#>  9 CERSOSIMO                        33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 10 CHOUHY TERRA                     33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 11 DAMBORIARENA                     33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 12 ESPALTER                         33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 13 FERNANDEZ CRESPO                 33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 14 GARZON                           33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 15 GOMEZ                            33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 16 GONZALEZ                         33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 17 ITURBIDE                         33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 18 MARTINEZ                         33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 19 MOREIRA                          33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 20 MORENO ZEBALLOS                  33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 21 OIS                              33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 22 OTERO                            33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 23 P R E S I D E N T E              33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 24 PUIG                             33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 25 RODRIGUEZ ROCHA                  33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 26 SALGADO                          33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 27 SEÑO                             33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 28 TROITIÑO                         33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~
#> 29 TUBINO                           33 CAMARA DE ~ NA     speech_e~     1 "SEÑO~

Como se observa, el objeto text2 que contiene nuestro diario de sesión en formato base de datos luce ordenado y limpio. Lo único que resta hacer es agregar la etiqueta partidaria con el paquete puy.

library(puy)

text2 <- add_party(text2)

print(text2, n = nrow(text2))
#> # A tibble: 33 x 12
#>    legislator      legislature chamber date   id        speech   sex legislator2
#>    <chr>                 <int> <chr>   <date> <chr>     <chr>  <dbl> <chr>      
#>  1 ANTUNEZ                  33 CAMARA~ NA     speech_e~ "SEÑO~     1 ANTUNEZ MA~
#>  2 ARISMENDI                33 CAMARA~ NA     speech_e~ "SEÑO~     1 ARISMENDI,~
#>  3 BRENA                    33 CAMARA~ NA     speech_e~ "SEÑO~     1 BRENA, Tom~
#>  4 BRUNERAU DES H~          33 CAMARA~ NA     speech_e~ "SEÑO~     1 BRUNERAU D~
#>  5 BRUNO                    33 CAMARA~ NA     speech_e~ "SEÑO~     1 BRUNO, Jos~
#>  6 BURANELLI                33 CAMARA~ NA     speech_e~ "SEÑO~     1 BURANELLI,~
#>  7 CALLERIZA                33 CAMARA~ NA     speech_e~ "SEÑO~     1 CALLERIZA,~
#>  8 CARDOSO                  33 CAMARA~ NA     speech_e~ "SEÑO~     1 CARDOSO, J~
#>  9 CERSOSIMO                33 CAMARA~ NA     speech_e~ "SEÑO~     1 CERSOSIMO,~
#> 10 CHOUHY TERRA             33 CAMARA~ NA     speech_e~ "SEÑO~     1 CHOUHY TER~
#> 11 CHOUHY TERRA             33 CAMARA~ NA     speech_e~ "SEÑO~     1 CHOUHY TER~
#> 12 DAMBORIARENA             33 CAMARA~ NA     speech_e~ "SEÑO~     1 DAMBORIARE~
#> 13 ESPALTER                 33 CAMARA~ NA     speech_e~ "SEÑO~     1 ESPALTER, ~
#> 14 FERNANDEZ CRES~          33 CAMARA~ NA     speech_e~ "SEÑO~     1 FERNANDEZ ~
#> 15 GARZON                   33 CAMARA~ NA     speech_e~ "SEÑO~     1 GARZON, Ex~
#> 16 GOMEZ                    33 CAMARA~ NA     speech_e~ "SEÑO~     1 GOMEZ, Eug~
#> 17 GONZALEZ                 33 CAMARA~ NA     speech_e~ "SEÑO~     1 GONZALEZ, ~
#> 18 GONZALEZ                 33 CAMARA~ NA     speech_e~ "SEÑO~     1 GONZALEZ, ~
#> 19 GONZALEZ                 33 CAMARA~ NA     speech_e~ "SEÑO~     1 GONZALEZ, ~
#> 20 GONZALEZ                 33 CAMARA~ NA     speech_e~ "SEÑO~     1 GONZALEZ, ~
#> 21 ITURBIDE                 33 CAMARA~ NA     speech_e~ "SEÑO~     1 ITURBIDE, ~
#> 22 MARTINEZ                 33 CAMARA~ NA     speech_e~ "SEÑO~     1 MARTINEZ, ~
#> 23 MOREIRA                  33 CAMARA~ NA     speech_e~ "SEÑO~     1 MOREIRA, J~
#> 24 MORENO ZEBALLOS          33 CAMARA~ NA     speech_e~ "SEÑO~     1 MORENO ZEB~
#> 25 OIS                      33 CAMARA~ NA     speech_e~ "SEÑO~     1 OIS, Martin
#> 26 OTERO                    33 CAMARA~ NA     speech_e~ "SEÑO~     1 OTERO, Juan
#> 27 P R E S I D E ~          33 CAMARA~ NA     speech_e~ "SEÑO~     1 <NA>       
#> 28 PUIG                     33 CAMARA~ NA     speech_e~ "SEÑO~     1 PUIG, Vent~
#> 29 RODRIGUEZ ROCHA          33 CAMARA~ NA     speech_e~ "SEÑO~     1 RODRIGUEZ ~
#> 30 SALGADO                  33 CAMARA~ NA     speech_e~ "SEÑO~     1 SALGADO, R~
#> 31 SEÑO                     33 CAMARA~ NA     speech_e~ "SEÑO~     1 <NA>       
#> 32 TROITIÑO                 33 CAMARA~ NA     speech_e~ "SEÑO~     1 TROITIÑO, ~
#> 33 TUBINO                   33 CAMARA~ NA     speech_e~ "SEÑO~     1 TUBINO, Ar~
#> # ... with 4 more variables: party <chr>, party_acron <chr>, indicator <int>,
#> #   words <dbl>

Lo que surge de agregar la etiqueta partidaria es que la mayoría de los políticos están en la base de politicos del paquete puy. Pero el problema es que hay datos duplicados con distinto nombre de legislador. Es decir, en dos casos hay más de un legislador que tiene el mismo apellido en la misma legislatura. En estos casos la solución es ir al diario de sesión y verificar en asistencia quien es el político que actuó en esa sesión. En este caso el nombre de los dos políticos que son de esta sesión son: CHOUHY TERRA, Jose L. y GONZALEZ, Carmelo R. De esta manera procedemos a eliminar a los otros legisladores y podemos dar por terminado el procesamiento de este diario de sesión.

text2 <- text2[-c(11, 17, 18, 19),] # marcamos las filas en las que están los legisladores que se deben ir
print(text2[, c(1,2, 7:ncol(text2))], n = Inf)
#> # A tibble: 29 x 8
#>    legislator    legislature   sex legislator2 party party_acron indicator words
#>    <chr>               <int> <dbl> <chr>       <chr> <chr>           <int> <dbl>
#>  1 ANTUNEZ                33     1 ANTUNEZ MA~ Part~ PCGR                2   327
#>  2 ARISMENDI              33     1 ARISMENDI,~ Part~ PC                  1   217
#>  3 BRENA                  33     1 BRENA, Tom~ Unio~ UC                  1   304
#>  4 BRUNERAU DES~          33     1 BRUNERAU D~ Part~ PC                  1     7
#>  5 BRUNO                  33     1 BRUNO, Jos~ Part~ PN                  1   462
#>  6 BURANELLI              33     1 BURANELLI,~ Part~ PN                  1   394
#>  7 CALLERIZA              33     1 CALLERIZA,~ Part~ PC                  1   540
#>  8 CARDOSO                33     1 CARDOSO, J~ Part~ PS                  1   162
#>  9 CERSOSIMO              33     1 CERSOSIMO,~ Part~ PC                  1   953
#> 10 CHOUHY TERRA           33     1 CHOUHY TER~ Part~ PC                  1   174
#> 11 DAMBORIARENA           33     1 DAMBORIARE~ Part~ PN                  1   505
#> 12 ESPALTER               33     1 ESPALTER, ~ Part~ PC                  1    44
#> 13 FERNANDEZ CR~          33     1 FERNANDEZ ~ Part~ PN                  1  1430
#> 14 GARZON                 33     1 GARZON, Ex~ Part~ PC                  1   451
#> 15 GOMEZ                  33     1 GOMEZ, Eug~ Part~ PCU                 1   371
#> 16 GONZALEZ               33     1 GONZALEZ, ~ Part~ PN                  1    54
#> 17 ITURBIDE               33     1 ITURBIDE, ~ Part~ PC                  1   958
#> 18 MARTINEZ               33     1 MARTINEZ, ~ Part~ PC                  1  1010
#> 19 MOREIRA                33     1 MOREIRA, J~ Part~ PC                  1   708
#> 20 MORENO ZEBAL~          33     1 MORENO ZEB~ Part~ PC                  1   144
#> 21 OIS                    33     1 OIS, Martin Part~ PN                  1     8
#> 22 OTERO                  33     1 OTERO, Juan Part~ PC                  1    98
#> 23 P R E S I D ~          33     1 <NA>        <NA>  <NA>               NA    12
#> 24 PUIG                   33     1 PUIG, Vent~ Part~ PN                  1  1070
#> 25 RODRIGUEZ RO~          33     1 RODRIGUEZ ~ Part~ PC                  1  1004
#> 26 SALGADO                33     1 SALGADO, R~ Part~ PN                  1  1255
#> 27 SEÑO                   33     1 <NA>        <NA>  <NA>               NA   163
#> 28 TROITIÑO               33     1 TROITIÑO, ~ Part~ PS                  1  1076
#> 29 TUBINO                 33     1 TUBINO, Ar~ Part~ PN                  1   484

Ejemplo 3

▶️ Un diario de sesión reciente de una sesión convencional de la Comisión Permanente del 17 de setiembre de 2019

Tomamos un diario de sesión reciente y aplicamos el mismo criterio que con los diarios anteriores: usamos speech_build() sin compilar para chequear que los nombres de los legisladores sean correctos para luego compilar.

url <- "https://parlamento.gub.uy/documentosyleyes/documentos/diario-de-sesion/comisionpermanente/6084/IMG/0?width=800&height=600&hl=en_US1&iframe=true&rel=nofollow"

text <- speech::speech_build(file = url)

print(text, n = nrow(text))
#> # A tibble: 24 x 7
#>    legislator speech                  chamber date       legislature id      sex
#>    <chr>      <chr>                   <chr>   <date>           <int> <chr> <dbl>
#>  1 BORDABERRY SEÑOR BORDABERRY. Pido~ COMISI~ 2019-09-17          48 0?wi~     1
#>  2 BORDABERRY SEÑOR BORDABERRY. Prop~ COMISI~ 2019-09-17          48 0?wi~     1
#>  3 AVIAGA     SEÑORA AVIAGA. Pido la~ COMISI~ 2019-09-17          48 0?wi~     0
#>  4 AVIAGA     SEÑORA AVIAGA. En el m~ COMISI~ 2019-09-17          48 0?wi~     0
#>  5 GOÑI       SEÑOR GOÑI. Pido la pa~ COMISI~ 2019-09-17          48 0?wi~     1
#>  6 GOÑI       SEÑOR GOÑI. El Frente ~ COMISI~ 2019-09-17          48 0?wi~     1
#>  7 MAHIA      SEÑOR MAHIA. Pido la p~ COMISI~ 2019-09-17          48 0?wi~     1
#>  8 MAHIA      SEÑOR MAHIA. Gracias, ~ COMISI~ 2019-09-17          48 0?wi~     1
#>  9 ABDALA     SEÑOR ABDALA. Voto por~ COMISI~ 2019-09-17          48 0?wi~     1
#> 10 ASTI       SEÑOR ASTI. Obviamente~ COMISI~ 2019-09-17          48 0?wi~     1
#> 11 AVIAGA     SEÑORA AVIAGA. Voto po~ COMISI~ 2019-09-17          48 0?wi~     0
#> 12 BORDABERRY SEÑOR BORDABERRY. Voto~ COMISI~ 2019-09-17          48 0?wi~     1
#> 13 GOÑI       SEÑOR GOÑI. Voto por D~ COMISI~ 2019-09-17          48 0?wi~     1
#> 14 LAZO       SEÑORA LAZO. Voto por ~ COMISI~ 2019-09-17          48 0?wi~     0
#> 15 MAHIA      SEÑOR MAHIA. Voto por ~ COMISI~ 2019-09-17          48 0?wi~     1
#> 16 MERONI     SEÑOR MERONI. Voto, co~ COMISI~ 2019-09-17          48 0?wi~     1
#> 17 PEREYRA    SEÑORA PEREYRA. Con mu~ COMISI~ 2019-09-17          48 0?wi~     0
#> 18 TOURNE     SEÑORA TOURNE. Voy a v~ COMISI~ 2019-09-17          48 0?wi~     0
#> 19 VIERA      SEÑOR VIERA. Voto por ~ COMISI~ 2019-09-17          48 0?wi~     1
#> 20 BORDABERRY SEÑOR BORDABERRY. Pido~ COMISI~ 2019-09-17          48 0?wi~     1
#> 21 BORDABERRY SEÑOR BORDABERRY. En l~ COMISI~ 2019-09-17          48 0?wi~     1
#> 22 BORDABERRY SEÑOR BORDABERRY. El s~ COMISI~ 2019-09-17          48 0?wi~     1
#> 23 ABDALA     SEÑOR ABDALA. Pido la ~ COMISI~ 2019-09-17          48 0?wi~     1
#> 24 ABDALA     SEÑOR ABDALA. Señora p~ COMISI~ 2019-09-17          48 0?wi~     1

Este diario de sesión no presenta problemas en los nombres de los legisladores por lo que podemos perfectamente ir directo a la compilación:

text <- speech::speech_build(file = url, compiler = TRUE)

print(text, n = nrow(text))
#> # A tibble: 11 x 7
#>    legislator legislature chamber             date       id         speech   sex
#>    <chr>            <int> <chr>               <date>     <chr>      <chr>  <dbl>
#>  1 ABDALA              48 COMISION PERMANENTE 2019-09-17 0?width=8~ SEÑOR~     1
#>  2 ASTI                48 COMISION PERMANENTE 2019-09-17 0?width=8~ SEÑOR~     1
#>  3 AVIAGA              48 COMISION PERMANENTE 2019-09-17 0?width=8~ SEÑOR~     0
#>  4 BORDABERRY          48 COMISION PERMANENTE 2019-09-17 0?width=8~ SEÑOR~     1
#>  5 GOÑI                48 COMISION PERMANENTE 2019-09-17 0?width=8~ SEÑOR~     1
#>  6 LAZO                48 COMISION PERMANENTE 2019-09-17 0?width=8~ SEÑOR~     0
#>  7 MAHIA               48 COMISION PERMANENTE 2019-09-17 0?width=8~ SEÑOR~     1
#>  8 MERONI              48 COMISION PERMANENTE 2019-09-17 0?width=8~ SEÑOR~     1
#>  9 PEREYRA             48 COMISION PERMANENTE 2019-09-17 0?width=8~ SEÑOR~     0
#> 10 TOURNE              48 COMISION PERMANENTE 2019-09-17 0?width=8~ SEÑOR~     0
#> 11 VIERA               48 COMISION PERMANENTE 2019-09-17 0?width=8~ SEÑOR~     1

Ahora podemos agregarle la etiqueta partidaria y el nombre completo a los legisladores con el paquete puy:

library(puy)
text <- add_party(text)

print(text, n = nrow(text))
#> # A tibble: 11 x 12
#>    legislator legislature chamber      date       id    speech   sex legislator2
#>    <chr>            <int> <chr>        <date>     <chr> <chr>  <dbl> <chr>      
#>  1 ABDALA              48 COMISION PE~ 2019-09-17 0?wi~ SEÑOR~     1 ABDALA, Pa~
#>  2 ASTI                48 COMISION PE~ 2019-09-17 0?wi~ SEÑOR~     1 ASTI, Alfr~
#>  3 AVIAGA              48 COMISION PE~ 2019-09-17 0?wi~ SEÑOR~     0 AVIAGA, Ca~
#>  4 BORDABERRY          48 COMISION PE~ 2019-09-17 0?wi~ SEÑOR~     1 BORDABERRY~
#>  5 GOÑI                48 COMISION PE~ 2019-09-17 0?wi~ SEÑOR~     1 GOÑI ROMER~
#>  6 LAZO                48 COMISION PE~ 2019-09-17 0?wi~ SEÑOR~     0 LAZO, Sand~
#>  7 MAHIA               48 COMISION PE~ 2019-09-17 0?wi~ SEÑOR~     1 MAHIA, Jos~
#>  8 MERONI              48 COMISION PE~ 2019-09-17 0?wi~ SEÑOR~     1 <NA>       
#>  9 PEREYRA             48 COMISION PE~ 2019-09-17 0?wi~ SEÑOR~     0 PEREYRA, S~
#> 10 TOURNE              48 COMISION PE~ 2019-09-17 0?wi~ SEÑOR~     0 TOURNE, Da~
#> 11 VIERA               48 COMISION PE~ 2019-09-17 0?wi~ SEÑOR~     1 VIERA, Tab~
#> # ... with 4 more variables: party <chr>, party_acron <chr>, indicator <int>,
#> #   words <dbl>

Debemos chequear si tenemos la etiqueta partidaria para todos los legisladores:

text[, c(1,2, 7:ncol(text))]
#> # A tibble: 11 x 8
#>    legislator legislature   sex legislator2    party party_acron indicator words
#>    <chr>            <int> <dbl> <chr>          <chr> <chr>           <int> <dbl>
#>  1 ABDALA              48     1 ABDALA, Pablo  Part~ PN                  1   394
#>  2 ASTI                48     1 ASTI, Alfredo  Fren~ FA                  1    44
#>  3 AVIAGA              48     0 AVIAGA, Carol  Part~ PN                  1   107
#>  4 BORDABERRY          48     1 BORDABERRY, P~ Part~ PC                  1   944
#>  5 GOÑI                48     1 GOÑI ROMERO, ~ Part~ PN                  2    94
#>  6 LAZO                48     0 LAZO, Sandra   Fren~ FA                  3   103
#>  7 MAHIA               48     1 MAHIA, Jose C~ Fren~ FA                  1   122
#>  8 MERONI              48     1 <NA>           <NA>  <NA>               NA    10
#>  9 PEREYRA             48     0 PEREYRA, Susa~ Fren~ FA                  1    12
#> 10 TOURNE              48     0 TOURNE, Daisy  Fren~ FA                  1   111
#> 11 VIERA               48     1 VIERA, Tabare  Part~ PC                  1     6

Como se puede observar hay un solo diputado o senador que la función puy::add_party() no logró identificar. Seguramente sea un diputado o senador suplente. Dependiendo del análisis posterior que se quiera hacer es si se busca por fuentes alternativas la filiación de este legislador o se lo puede descartar. La función puy::add_party() además de agregar el partido y el nombre completo del legislador agrega una variable a partir de la función del paquete speech que hace un conteo de palabras: speech_word_count(). Esta variable puede ser de utilidad para estos casos por ejemplo, es decir, descartar a este legislador puede que no tenga un impacto significativo ya que solo dice 10 palabras (las cuales seguramente sean: “Si voto…”).

Por último, si por alguna razón necesitamos, luego de tener la base de datos compilada, que cada fila se corresponda con cada una de las intervención de un legislador y que el texto no se encuentre agrupado, es posible usar la función speech::speech_uncompiler() cuyo único argumento tidy_speech se corresponde con el resultado de la aplicación de speech_build(., compiler = TRUE).

Ejemplo 4

▶️ Descarga masiva de sesiones correspondiente a un período de tiempo detarminado: Cámara de Representantes del 20-11-2014 al 20-11-2020

Si necesitamos obtener la información sobre las intervenciones correspondiente a un rango de fechas determinado, es posible usar la función speech::speech_url() que permite scrapear (descargar directamente de la web) las URL de las sesiones correspondientes y alojarlas en un vector que luego servirá como argumento de la función speech::speech_build(). Tal como se muestra en el ejemplo, necesito obtener información ordenada de todos los diarios de sesión de la Cámara de Representantes, entre el 20-11-2014 y el 20-11-2020, lo cual incluye sesiones correspondientes a tres legislaturas diferentes.

sesiones <- speech::speech_url(chamber = "D", from = "20-11-2014", to = "20-11-2015")
length(sesiones)
#> [1] 54

Esta función busca simplificar el procedimiento de obtención de URL o descarga de diarios de sesión de forma manual, ya que automatiza la descarga de las mismas.

Posibles aplicaciones

A continuación se muestran algunas posibles aplicaciones de speech, a partir del análisis de los discursos vinculados a la discusión de la Ley de Urgente Consideración (LUC) en la Cámara de Senadores del 5 de junio de 2020.

Al igual que en los ejemplos precedentes, comenzamos utilizando la función speech_build() para descargar las intervenciones que me interesan, así como agregando la etiqueta partidaria con puy::add_party().

url <- "https://parlamento.gub.uy/documentosyleyes/documentos/diario-de-sesion/senadores/6145/IMG/0?width=800&height=600&hl=en_US1&iframe=true&rel=nofollow"

intervenciones <- speech::speech_build(file = url)
intervenciones <- puy::add_party(intervenciones)

Luego, como primer paso para explorar el contenido de los discursos de una sesión o conjunto de sesiones, podríamos usar el paquete quanteda para definir un corpus con las intervenciones y generar un document-feature-matrix que permitirá realizar análisis y visualizaciones. Para ello, realizo algunas tareas de limpieza del texto como normalizar el texto en minúscula, remover los conectores, artículos y palabras de menos de tres caracteres, eliminar los nombres de los legisladores, las puntuaciones y los números.

library(dplyr)
dfm_intervenciones <- quanteda::dfm(quanteda::tokens(intervenciones$speech,
                                    remove_punct = TRUE,
                                    remove_numbers = TRUE),
                                    tolower=TRUE,
                                    verbose = FALSE) %>%
                                    quanteda::dfm_remove(pattern = c(quanteda::stopwords("spanish"), 
                                                                     tolower(intervenciones$legislator)), min_nchar = 3) %>%
                                    quanteda::dfm_group(groups = intervenciones$party)

En segundo lugar, generamos una nube de palabras segmentada por partido al que pertenece el legislador. A partir del análisis de los términos más frecuentes se observan diferencias en el foco de la discusión de la Ley entre los partidos:

quanteda.textplots::textplot_wordcloud(dfm_intervenciones, 
                                       min.count = 2, 
                                       max_words = 500,
                                       random.order = FALSE ,
                                       colors = RColorBrewer::brewer.pal(8,"Dark2"),
                                       comparison = TRUE)

Utilizamos la función quanteda::textstat_simil() de quanteda para construir una matriz de distancias (según co-ocurrencia) y calcular la correlación entre un término, en este caso “luc”,y otras palabras que aparecen en las intervenciones. A continuación se imprimen las 15 palabras con mayor correlación con dicho término.

quanteda.textstats::textstat_simil(dfm_intervenciones,selection = "luc",
method = "correlation",margin = "features")%>%
  as.data.frame()%>%
  dplyr::arrange(-correlation)%>%
  dplyr::top_n(15)
#>       feature1 feature2 correlation
#> 1  metodología      luc   1.0000000
#> 2       quince      luc   0.9997940
#> 3       pensar      luc   0.9995838
#> 4       existe      luc   0.9995678
#> 5      energía      luc   0.9992105
#> 6  posibilidad      luc   0.9990999
#> 7      bancada      luc   0.9990734
#> 8     senadora      luc   0.9989856
#> 9   desarrollo      luc   0.9989171
#> 10    vivienda      luc   0.9988989
#> 11       según      luc   0.9986741
#> 12       marco      luc   0.9983689
#> 13    profunda      luc   0.9983377
#> 14        lado      luc   0.9980516
#> 15    comisión      luc   0.9980132

Así también podemos ver con la función quanteda::kwic() el contexto de aparición de una palabra, término o frase, según una ventana (cantidad de palabras previas y posteriores) determinada, en este caso 15. Extraer el contexto de ciertos términos puede ser de utilidad para construir un nuevo corpus y realizar un análisis focalizado y/o comparativo.

quanteda::kwic(quanteda::tokens(intervenciones$speech,
                                remove_punct = TRUE,
                                remove_numbers = TRUE), 
                                pattern = quanteda::phrase(c("ley de urgente consideración")),
                                window = 15)

Por último, con el paquete syuzhet analizo el sentimiento de las intervenciones agrupadas por partido. La función syuzhet::get_sentiment() establece un puntaje resumen al texto a partir de la aparición de palabras en diccionarios de sentimientos que identifican cada una como positiva o negativa. En este caso vemos el posicionamiento de las menciones de los legisladores que participan en la discusión en la Cámara de Senadores, en la cual las intervenciones de la oposición tienen un puntaje sensiblemente más negativo que los partidos de la coalición.

library(ggplot2)

intervenciones %>%
    filter(party != "NA") %>%
    group_by(party) %>%
    summarise(speech_p = paste(speech, collapse = " ")) %>%
    mutate(Sentiment_syuzhet = syuzhet::get_sentiment(speech_p, method = "syuzhet", language = "spanish")) %>%
    ggplot(aes(x = factor(party, level = c("Frente Amplio", 
                                           "Cabildo Abierto", 
                                           "Partido Colorado", 
                                           "Partido Nacional")), 
               y = Sentiment_syuzhet, color = party)) +
    geom_point(size = 5, alpha = 0.8) +
    ggtitle("Análisis de sentimiento por Partido", 
            subtitle = "Discusión sobre Ley de Urgente Consideración (LUC) en la Cámara de Senadores (05/06/2020)") +
    geom_hline(yintercept = 0, color = "#4F4D4D") +
    theme_minimal() +
    theme(axis.title.y = element_blank(), 
          axis.title.x = element_blank(),
          legend.title = element_blank(), 
          legend.position = "none") 

Usos

En esta sección se deja constancia del uso que distintos usuarios hacen o han hecho del paquete speech.

Aplicación web

En este link se puede acceder a la aplicacion web para realizar los procesos básicos que se detallan en los ejemplos explorados arriba.

About

Ejemplos y usos del paquete de R 'speech'.

Resources

Stars

Watchers

Forks