在R中循环文件及其内容

时间:2015-03-31 13:09:23

标签: r loops

跟进on a question I only posted minutes ago,我需要提出另一个问题。上一个问题没有注意到我还必须查看每个文件的内容。换句话说,我必须遍历目录中的所有文件,通过每个文件的每一行。

每个文件名都是这样的。

airbag.WS-U-E-A.lst

.是分隔符,.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>

我想要做的是,在R中创建一个包含所有文件数据的新数据集。理想情况下它看起来像这样:

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只是行的id,可以像这样完成:

row.names <- "id"

filename是文件的名称(显然),which I can do like so

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

然后,我可以从文件名中删除wordcomponent

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

现在出现了我尚未想到的困难部分......

我上面写的所有命令都可以通过 循环文件并获取文件名来完成。但是,正如我所说,每个文件包含多个句子,我需要剖析并放在不同的行上。见上面的例子。你会看到文件名,单词和组件是相同的 - 但左右上下文却不相同。那是因为它们是两个不同的句子,在同一个文件中。

使用两个文件的例子可能会让我的问题更加清晰。

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>

如果这些是我目录中唯一的两个文件,我的R命令将执行以下操作:

  • 查看每个单独的文件
  • 将每个句子(即每一行)放入新行
  • 根据该句子所在的文件,填写文件名,单词和组件
  • 使用正则表达式,从句子
  • 获取左右上下文
  • 每行分配ID

输出看起来像这样

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

(为了简洁起见我遗漏了一些内容,用 [...] 表示)

我理解这似乎是一个很大的问题,但基本上我需要的是一种循环文件本身的方法,并将每行的行提取到一个新行,同时将有关文件本身的信息放在单独的列中(在同一行)。从行中提取文本是我应该能够自己完成的。例如,如果我能得到这样的东西,它会给我带来很长的路要走:

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>

我希望我很清楚我想说的是什么。如果没有随意问。

3 个答案:

答案 0 :(得分:0)

创建两个data.frames并合并它们

# 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)

答案 1 :(得分:0)

#set工作目录,如(setwd函数)所示,并手动将所有文件移动到一个目录中,因此分析很好,干净。您必须决定将所有文件保存在目录中的位置。下面,我向您展示了我将所有文件保存在“test”目录中。

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)

输出:

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

答案 2 :(得分:-1)

您可以使用readLines从文件中提取数据。在您的情况下,您可以使用嵌套循环来构建数据 - 一个循环遍历文件,并在其中,每行一个循环。

例如,我在~/test目录中设置了一些文件:

$ ls ~/test
file1.txt   file2.txt

文件看起来像这样:

$ 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.

现在我可以遍历它们并获取文件名和内容 - 我没有做任何正则表达式或处理这些信息,因为你已经表明你可以自己这样做。这仅仅是为了说明如何使用两个循环将文件名和文件内容中的信息添加到同一行:

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
  }
}

这导致以下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.

使用这样的rbind可能不是最有效的方法。另一种可能更有效的方法是为最终数据帧中的每一列构建一个向量,然后在完成后从这些向量中创建数据帧。这样可以避免潜在的昂贵的rbind()操作。