I uploaded a .txt
file in to R
as follows: Election_Parties <- readr::read_lines("Election_Parties.txt")
The following text is in the file: pastebin link.
The text more or less looks as follows (Please use actual file for solution!):
BOLIVIA
P1-Nationalist Revolutionary Movement-Free Bolivia Movement (Movimiento
Nacionalista Revolucionario [MNR])
P19-Liberty and Justice (Libertad y Justicia [LJ])
P20-Tupak Katari Revolutionary Movement (Movimiento Revolucionario Tupak Katari [MRTK])
COLOMBIA
P1-Democratic Aliance M-19 (Alianza Democratica M-19 [AD-M19])
P2-National Popular Alliance (Alianza Nacional Popular [ANAPO])
P3-Indigenous Authorities of Colombia (Autoridades Indígenas
de Colombia)
I would like to have all information about a party on one line, no matter how long it is.
DESIRED OUTPUT:
BOLIVIA
P1-Nationalist Revolutionary Movement-Free Bolivia Movement (Movimiento Nacionalista Revolucionario
P19-Liberty and Justice (Libertad y Justicia [LJ])
P20-Tupak Katari Revolutionary Movement (Movimiento Revolucionario Tupak Katari [MRTK])
COLOMBIA
P1-Democratic Aliance M-19 (Alianza Democratica M-19 [AD-M19])
P2-National Popular Alliance (Alianza Nacional Popular [ANAPO])
P3-Indigenous Authorities of Colombia (Autoridades Indígenas de Colombia)
The following answer: strsplit(paste(Election_Parties, collapse=" "), "\\s+(?=P\\d+-)", perl=TRUE)[[1]]
from this LINK, works to correct the strings, but it does not deal with the headers (BOLIVIA, COLUMBIA & the empty lines) properly. Dealing with this is important because I want to apply this solution afterwards.
Although I got an answer in the commentsof that post which worked on the example, it does not work on my text file.
How can I adapt the solution to deal with (leave alone) the headers and empty lines?
I turned the whole thing into a tidy and useful format. Have a look:
First I read in the file:
lines <- readr::read_lines("https://pastebin.com/raw/jSrvTa7G")
head(lines)
#> [1] ""
#> [2] "ALBANIA"
#> [3] "P1-Democratic Alliance Party (Partia Aleanca Democratike [AD])"
#> [4] "P2-National Unity Party (Partia Uniteti Kombëtar [PUK])"
#> [5] "P3-Social Spectrum Parties-Party of National Unity (Partitë e Spektrit Social-Partia e Unitetit Kombëtar"
#> [6] "[PSHS-PUK])"
I split the raw format into entries by looking for empty lines, which occur just before a new entry:
entries <- split(lines, cumsum(grepl("^$|^ $", lines)))
Then I loop through every entry and turn it into a tibble
:
library(stringr)
library(dplyr)
df <- lapply(entries, function(entry) {
entry <- entry[!grepl("^$|^ $", entry)] # remove empty elements
header <- entry[1] # first non empty is the header
entry <- tail(entry, -1) # remove header from entry
desc <- str_extract(entry, "^P\\d+-") # extract description
for (l in which(is.na(desc))) { # collapse lines that go over 2 elements
entry[l - 1] <- paste(entry[l - 1], entry[l], sep = " ")
}
entry <- entry[!is.na(desc)]
desc <- desc[!is.na(desc)]
# turn into nice format
df <- tibble::tibble(
header,
desc,
entry
)
df$entry <- str_replace_all(df$entry, fixed(df$desc), "") # remove description from entry
return(df)
}) %>%
bind_rows() # turn list into one data.frame
And now we have a really nice data.frame
we can easily work with:
df
#> # A tibble: 5,525 x 3
#> header desc entry
#> <chr> <chr> <chr>
#> 1 ALBANIA P1- Democratic Alliance Party (Partia Aleanca Democratike [AD~
#> 2 ALBANIA P2- National Unity Party (Partia Uniteti Kombëtar [PUK])
#> 3 ALBANIA P3- Social Spectrum Parties-Party of National Unity (Partitë ~
#> 4 ALBANIA P4- Alliance Party for Solidarity and Welfare (Partia Aleanca~
#> 5 ALBANIA P5- Albanian Democratic Union-Alliance for Freedom, Justice a~
#> 6 ALBANIA P6- Liberal Democrat Party (Partia Bashkimi Liberal Demokrat ~
#> 7 ALBANIA P7- Linking Blerta Albanian Party (Partia Lidhja e Blertë Shq~
#> 8 ALBANIA P8- Democratic Movement for Integration (Lëvizja Demokratike ~
#> 9 ALBANIA P9- Movement of Human Rights and Freedoms Party (Partia Lëviz~
#> 10 ALBANIA P10- Socialist Party of Albania (Partia Socialiste e Shqipëris~
#> # ... with 5,515 more rows
The strings which are scattered over multiple lines are corrected in this bit:
for (l in which(is.na(desc))) { # collapse lines that go over 2 elements
entry[l - 1] <- paste(entry[l - 1], entry[l], sep = " ")
}
desc
will be NA
in cases where the line does not begin with e.g., "P1-" (1 can be any number). If this is the case the line is collapse with the previous entry. Later on NA
are removed leaving the information only in the correct line.