Loop files and their contents in R

Following on from a question I posted just a few minutes ago , I need to ask another question. It was not noted in the previous question that I also have to view the contents of each individual file. In other words, I need to iterate over all the files in the directory and through each line of each file.

Each filename looks like this.

airbag.WS-U-E-A.lst

      

.

delimiter, .lst

extension (read as text).

Each file contains data per line like

/home/nobackup/SONAR/COMPACT/WR-U-E-A/WR-U-E-A0000075.data.ids.xml:  <sentence>ja voor den airbag op te pompen eh :p</sentence>
/home/nobackup/SONAR/COMPACT/WR-U-E-A/WR-U-E-A0000129.data.ids.xml:  <sentence>Dobby , als ze valt heeft ze dan wel al ne airbag hee</sentence>

      

What I want to do is, in R, create a new dataset containing data from all files. Ideally it would look like this:

ID | filename             | word | component | left-context                               | right-context
----------------------------------------------------------------------------------------------------------------
1    airbag.WS-U-E-A.lst   airbag   WS-U-E-A    ja voor den                                  op te pompen eh :p
2    airbag.WS-U-E-A.lst   airbag   WS-U-E-A    Dobby , als ze valt heeft ze dan wel al ne   hee

      

ID

is just a string identifier, you can do this:

row.names <- "id"

      

filename

is the name of the file (obviously) which I can do like this ::

files <- list.files(pattern="*.lst", full.names=T, recursive=FALSE)
d <- data.frame(fileName = unname(sapply(files, basename)))

      

Then I can remove word

and component

from the filename

d$word <- gsub("\\..+", "", d$fileName, perl=TRUE)
d$component <- gsub("^[^.]+.", "", d$fileName, perl=TRUE)
d$component <- gsub(".lst$", "", d$component, perl=TRUE)

      

Now comes the tricky part that I haven't figured out yet ...

All the commands I wrote above can only be executed by looping the files and getting their filename. However, as I said, each file contains several sentences that I need to parse and place on different lines. See example above. You will see that the filename, word, and component are identical, but the left and right contexts are not the same. This is because they are two different sentences in the same file.

Perhaps the two file example makes my question clearer.

adapter.WR-P-P-F.lst

/home/nobackup/SONAR/COMPACT/WR-P-P-F/WR-P-P-F0000026.data.ids.xml:  <sentence>Een aanpassingseenheid ( adapter ) , aangebracht in een behuizing voornamelijk bestaande uit in- en uitvoereenheden , een koppeleenheid , een geheugeneenheid , een besturingseenheid ( met actieve en passieve elementen en monolitische geïntegreerde schakelingen ) en een elektrische voedingseenheid . &gt;</sentence>
/home/nobackup/SONAR/COMPACT/WR-P-P-F/WR-P-P-F0000026.data.ids.xml:  <sentence>ID=&quot;1&quot;&gt;Het toestel ( adapter ) draagt zorg voor de overbrenging van gegevens , met een snelheid van 10 Mbps ( megabits per seconde ) , tussen meerdere automatische gegevensverwerkende machines in een digitaal netwerk . &quot; &gt;</sentence>
/home/nobackup/SONAR/COMPACT/WR-P-P-F/WR-P-P-F0000034.data.ids.xml:  <sentence>Overwegende dat deze sensoren niet zijn ontworpen op de installatie van een gepantserde kabel ; dat de mogelijkheid moet worden geboden dat de gepantserde kabel niet verplicht wordt gesteld voor de aansluiting tussen de sensor en de adapter , maar alleen van de adapter naar het controleapparaat ; dat het bijgevolg noodzakelijk is de verordening dienovereenkomstig te wijzigen ;</sentence>

      

airbag.WS-U-E-A.lst

/home/nobackup/SONAR/COMPACT/WR-U-E-A/WR-U-E-A0000075.data.ids.xml:  <sentence>ja voor den airbag op te pompen eh :p</sentence>
/home/nobackup/SONAR/COMPACT/WR-U-E-A/WR-U-E-A0000129.data.ids.xml:  <sentence>Dobby , als ze valt heeft ze dan wel al ne airbag hee</sentence>

      

If there were only two files in my directory, my R commands did the following:

  • View each individual file
  • Put each sentence (i.e. each line) on a new line
  • Based on which file this sentence is in, fill in the file name, word and component
  • With regular expressions, get the left and right context from a sentence
  • Assign IDs to each row

The result will look like this:

ID | filename             | word | component | left-context                               | right-context
----------------------------------------------------------------------------------------------------------------
1    adapter.WR-P-P-F.lst  adapter  WR-P-P-F    Een aanpassingseenheid (                     ) , aangebracht in een behuizing voornamelijk bestaande uit in- en uitvoere[...]
2    adapter.WR-P-P-F.lst  adapter  WR-P-P-F    ID=&quot;1&quot;&gt;Het toestel (            ) draagt zorg voor de overbrenging van gegevens [...]
3    adapter.WR-P-P-F.lst  adapter  WR-P-P-F    [...] tussen de sensor en de                 naar het controleapparaat ; [...]
4    airbag.WS-U-E-A.lst   airbag   WS-U-E-A    ja voor den                                  op te pompen eh :p
5    airbag.WS-U-E-A.lst   airbag   WS-U-E-A    Dobby , als ze valt heeft ze dan wel al ne   hee

      

(I left some content for the sake of brevity, indicated by [...] )

I realize this seems like a pretty big question, however I basically want a way to loop over the files themselves and extract the line in line to a new line, while at the same time entering information about the file itself in separate columns (on the same line). Extracting text from strings is something I would have to do myself. For example, it would take me a long way if I could just get something like this:

ID | filename             | word | component | sentence
----------------------------------------------------------------------------------------------------------------
1    adapter.WR-P-P-F.lst  adapter  WR-P-P-F   /home/nobackup/SONAR/COMPACT/WR-P-P-F/WR-P-P-F0000026.data.ids.xml:  <sentence>Een aanpassingseenheid ( adapter ) , aangebracht in een behuizing voornamelijk bestaande uit in- en uitvoereenheden , een koppeleenheid , een geheugeneenheid , een besturingseenheid ( met actieve en passieve elementen en monolitische geïntegreerde schakelingen ) en een elektrische voedingseenheid . &gt;</sentence>
2    adapter.WR-P-P-F.lst  adapter  WR-P-P-F   /home/nobackup/SONAR/COMPACT/WR-P-P-F/WR-P-P-F0000026.data.ids.xml:  <sentence>ID=&quot;1&quot;&gt;Het toestel ( adapter ) draagt zorg voor de overbrenging van gegevens , met een snelheid van 10 Mbps ( megabits per seconde ) , tussen meerdere automatische gegevensverwerkende machines in een digitaal netwerk . &quot; &gt;</sentence>
3    adapter.WR-P-P-F.lst  adapter  WR-P-P-F   /home/nobackup/SONAR/COMPACT/WR-P-P-F/WR-P-P-F0000034.data.ids.xml:  <sentence>Overwegende dat deze sensoren niet zijn ontworpen op de installatie van een gepantserde kabel ; dat de mogelijkheid moet worden geboden dat de gepantserde kabel niet verplicht wordt gesteld voor de aansluiting tussen de sensor en de adapter , maar alleen van de adapter naar het controleapparaat ; dat het bijgevolg noodzakelijk is de verordening dienovereenkomstig te wijzigen ;</sentence>
4    airbag.WS-U-E-A.lst   airbag   WS-U-E-A   /home/nobackup/SONAR/COMPACT/WR-U-E-A/WR-U-E-A0000075.data.ids.xml:  <sentence>ja voor den airbag op te pompen eh :p</sentence>
5    airbag.WS-U-E-A.lst   airbag   WS-U-E-A   /home/nobackup/SONAR/COMPACT/WR-U-E-A/WR-U-E-A0000129.data.ids.xml:  <sentence>Dobby , als ze valt heeft ze dan wel al ne airbag hee</sentence>

      

Hope it's clear what I am trying to say. If you can't ask.

+1


source to share


3 answers


Create two data.frames and combine them



# what you have so far (file-level data.frame)
files <- list.files(pattern="*.lst", full.names=T, recursive=FALSE)
d <- data.frame(fileName = unname(sapply(files, basename)))
d$word <- gsub("\\..+", "", d$fileName, perl=TRUE)
d$component <- gsub("^[^.]+.", "", d$fileName, perl=TRUE)
d$component <- gsub(".lst$", "", d$component, perl=TRUE)

# new data.frame containing contents of files
e <- do.call(rbind, lapply(files, function(x) {
    # create two-column data.frame for each file
    ## first column is fileName
    ## second column is data from each file
    data.frame(fileName = x, sentence = readLines(x), stringsAsFactors = FALSE)
}))
# the above returns a data.frame `e` containing all file records    

# pull out the sentence (probably better ways to do this)
e$sentence <- sapply(strsplit(e$sentence, ".xml: ", fixed = TRUE), `[`, 2)
e$sentence <- gsub("<sentence>", "", e$sentence, fixed = TRUE)
e$sentence <- gsub("</sentence>", "", e$sentence, fixed = TRUE)

# merge `d` and `e` by the common column name `fileName`
out <- merge(d, e, by = "fileName", all = TRUE)

# extract your two "context" variables by splitting the sentence variable by `word`
contexts <- strsplit(out$sentence, out$word)
## this is the left-context (everything to the left of the word)
out$`left-context` <- sapply(contexts, `[`, 1)
## this is the right-context (everything to the right of the word)
out$`right-context` <- sapply(contexts, `[`, 2)

      

0


source


#set the working directory as shown in (setwd function) and manually move all your files into one directory to keep the analysis nice and clean. You must decide where to store all the files in the directory. Below I showed you that I saved all my files in a "test" directory.

setwd("C:/Users/username/Desktop/test")  #windows
setwd("/home/username/Desktop/test")  #linux    

files <- list.files()

df2 <- data.frame(matrix(nrow = 1, ncol = 5), stringsAsFactors = FALSE)

colnames(df2) <- c("filename", "word", "component", "left_context", "right_context")

for(i in files){

  word = sub("([a-z]+)(.)([A-Z-]+)(.*)", "\\1", i)

  component = sub("([a-z]+)(.)([A-Z-]+)(.*)", "\\3", i)

  list1 <- scan(i, sep = ">", what = list("character", "character"))

  context = unlist(lapply(list1[[2]], function(x) gsub('</sentence', '', x) ))

  for(j in 1:length(context)){

    left_context = strsplit(context[j], word)[[1]][1]

    right_context = strsplit(context[j], word)[[1]][2]

    df1 <- data.frame(filename = i, 
                      word = word,
                      component = component,
                      left_context = left_context,
                      right_context = right_context,
                      stringsAsFactors = FALSE)

    df2 <- rbind(df2, df1)

  }
}

df2 <- df2[2:nrow(df2),]

df2 <- cbind(data.frame(ID = 1:nrow(df2), stringsAsFactors = FALSE), df2)

View(df2)

      



output:

print(df2)
ID                 filename    word component  left_context                                                                                                                                                                                                                             right_context
1 adapter.WR-P-P-F.lst.txt adapter  WR-P-P-F  Een aanpassingseenheid (                                                                                                                                                                                                                  ) , aangebracht in een behuizing voornamelijk bestaande uit in- en uitvoereenheden , een koppeleenheid , een geheugeneenheid , een besturingseenheid ( met actieve en passieve elementen en monolitische geïntegreerde schakelingen ) en een elektrische voedingseenheid . &gt;
2 adapter.WR-P-P-F.lst.txt adapter  WR-P-P-F  ID=&quot;1&quot;&gt;Het toestel (                                                                                                                                                                                                         ) draagt zorg voor de overbrenging van gegevens , met een snelheid van 10 Mbps ( megabits per seconde ) , tussen meerdere automatische gegevensverwerkende machines in een digitaal netwerk . &quot; &gt;  
3 adapter.WR-P-P-F.lst.txt adapter  WR-P-P-F  Overwegende dat deze sensoren niet zijn ontworpen op de installatie van een gepantserde kabel ; dat de mogelijkheid moet worden geboden dat de gepantserde kabel niet verplicht wordt gesteld voor de aansluiting tussen de sensor en de  , maar alleen van de 
4  airbag.WS-U-E-A.lst.txt  airbag  WS-U-E-A  ja voor den                                                                                                                                                                                                                               op te pompen eh :p
5  airbag.WS-U-E-A.lst.txt  airbag  WS-U-E-A  Dobby , als ze valt heeft ze dan wel al ne                                                                                                                                                                                                hee

      

0


source


You can extract data from files using readLines

. In your case, you can use nested loops to create your data - one to iterate over files, and inside that, a loop on each line.

As an example, I installed several files in a directory ~/test

:

$ ls ~/test
file1.txt   file2.txt

      

The files look like this:

$ ls | xargs cat
I am line 1 from file1.
I am line 2 from file1.
I am line 1 from file2.
I am line 2 from file2.

      

Now I can skip them and grab the filename and its contents. I am not doing any regex or processing this information as you pointed out that you can do it yourself. This is just to illustrate how you can use two loops to add information from the file name and file content on one line:

dir <- '~/test'
df <- data.frame(filename=c(), row.index=c(), row.contents=c())
for (file in list.files(dir)) { 
  filename = paste0(dir, '/', file)
  i <- 1
  for (line in readLines(filename)) { 
    df <- rbind(df, data.frame(filename=filename, row.index=i, row.contents=line))
    i <- i + 1
  }
}

      

This leads to the following data. frame:

> df
          filename row.index            row.contents
1 ~/test/file1.txt         1 I am line 1 from file1.
2 ~/test/file1.txt         2 I am line 2 from file1.
3 ~/test/file2.txt         1 I am line 1 from file2.
4 ~/test/file2.txt         2 I am line 2 from file2.

      

Using rbind like this is probably not the most efficient way to do this. Another way, which is likely to be more efficient, would be to create a vector for each column in your final dataframe, and then create data from those vectors once you're done. This avoids the potentially expensive rbind () operation.

-1


source







All Articles