2016-12-04 94 views
0

在RI在嘗試導入使用以下結構的大量文本文件:這是保存爲一個example.txt的例子:在R中,如何從分割數據的文本文件創建數據框?

Curve Name: 
    Curve A 
Curve Values: 
    index Variable 1 Variable 2 
        [°C]   [%] 
    0    30   100 
    1    40   95 
    2    50   90 
Curve Color: 
    Blue 

Curve Name: 
    Curve B 
Curve Values: 
    index Variable 1 Variable 2 
        [°C]   [%] 
    0    30   100 
    1    40   90 
    2    50   80 
Curve Color: 
    Green 

到目前爲止,我可以提取名稱和顏色

file.text <- readLines("example.txt") 

curve.names <- trimws(file.text[which(regexpr('Curve Name:', file.text) > 0) + 1]) 
curve.colors <- trimws(file.text[which(regexpr('Curve Color:', file.text) > 0) + 1]) 

如何使用curve.name創建一個數據框作爲因子,其他值在下面的結構中用數字表示?

curve.name index variable.1 variable.2 
    Curve A 0    30   100 
    Curve A 1    40   95 
    Curve A 2    50   90 
    Curve B 0    30   100 
    Curve B 1    40   90 
    Curve B 2    50   80   

回答

1

一般很多grep。尋找一種方法來組條目,就像一個空行的累計總和,都可以得心應手,以及:

l <- readLines(textConnection('Curve Name: 
    Curve A 
Curve Values: 
    index Variable 1 Variable 2 
        [°C]   [%] 
    0    30   100 
    1    40   95 
    2    50   90 
Curve Color: 
    Blue 

Curve Name: 
    Curve B 
Curve Values: 
    index Variable 1 Variable 2 
        [°C]   [%] 
    0    30   100 
    1    40   90 
    2    50   80 
Curve Color: 
    Green ')) 

do.call(rbind, 
     lapply(split(trimws(l), cumsum(l == '')), function(x){ 
      data.frame(
       curve = x[grep('Curve Name:', x) + 1], 
       read.table(text = paste(x[(grep('index', x) + 2):(grep('Curve Color:', x) - 1)], 
             collapse = '\n'), 
          col.names = c('index', 'variable.1', 'varible.2')))})) 
##  curve index variable.1 varible.2 
## 0.1 Curve A  0   30  100 
## 0.2 Curve A  1   40  95 
## 0.3 Curve A  2   50  90 
## 1.1 Curve B  0   30  100 
## 1.2 Curve B  1   40  90 
## 1.3 Curve B  2   50  80 
+0

我投了所有的答案;但是,選擇了這一個是因爲它可以處理可變長度曲線而無需額外的軟件包閱讀「Curve Values:」的累計總和適用於我所遇到的問題。 – Agriculturist

3

假設每個文件從上面具有完全相同的格式:

txt <- readLines("example.txt") 
curve_name <- rep(trimws(txt[c(2,13)]), each=3) 
curve_color <- rep(trimws(txt[c(10,21)]), each=3) 
val <- read.table(text=paste(txt[c(6:8, 17:19)], collapse = "\n")) 
colnames(val) <- c("index", "var1", "var2") 
cbind(curve_name, curve_color, val) 

如果格式不完全上面一個,你可以嘗試通過頭部的找出線路指數。因此,尋找在那裏說:Curve Values:

其中給出:

curve_name curve_color index var1 var2 
1 Curve A  Blue  0 30 100 
2 Curve B  Blue  1 40 95 
3 Curve A  Blue  2 50 90 
4 Curve B  Green  0 30 100 
5 Curve A  Green  1 40 90 
6 Curve B  Green  2 50 80 
2

讀線到LCurve Color之前清除一切空間。 (如果在實際文件中Curve Color之前沒有空格,但是在Curve Color之前有一個空格,則刪除空格可能不是必需的。)然後重新讀取以創建variables data.frame的數字開頭的行。然後使用read.dcf閱讀rest,並使用cbind將兩者合併。

我們假設

  1. 曲線值排第二,所以我們可以從rest使用數字表中[, -2]
  2. 只有行以數字(以空格開頭)忽略它。
  3. 每個數字記錄都有3列,並在問題中顯示列名。行的索引號爲0,同一記錄中的後續行也不包含0 index數字。 (每個數字表中的行數沒有限制,不同的記錄可能具有不同數量的這種行)。

沒有使用包。

L <- sub("^ *Curve Color", "Curve Color", readLines("example.txt")) 
variables <- read.table(text = grep("^\\d", trimws(L), value = TRUE), 
col.names = c("index", "variable.1", "variable.2")) 
rest <- trimws(read.dcf(textConnection(L))[, -2]) 
cbind(rest[cumsum(variables$index == 0), ], variables) 

,並提供:

Curve Name Curve Color index variable.1 variable.2 
1 Curve A  Blue  0   30  100 
2 Curve A  Blue  1   40   95 
3 Curve A  Blue  2   50   90 
4 Curve B  Green  0   30  100 
5 Curve B  Green  1   40   90 
6 Curve B  Green  2   50   80 
+0

基於不同的記錄可以表示數字表中不同數量的行的海報評論,修改了代碼以允許這樣做。還有一些簡化,所以代碼不再比以前。 –

3

略有不同的方法預測的假設格式。我們獲得每個「記錄」,提取突出的組件並將它們全部綁定在一起。

library(purrr) 
library(stringi) 

starts <- which(grepl("Curve Name:", lines)) # find the start of each record 
ends <- which(grepl("Curve Color:", lines))+1 # find the end of each record 

map2_df(starts, ends, function(start, end) { 

    rec <- paste0(lines[start:(end)], collapse="\n") # extract the record 

    # regex extract each set of values 
    stri_match_first_regex(rec, c("Curve Name:[[:space:]]+([[:alnum:][:blank:]]+)", 
           "Curve Values:[[:space:]]+([[:print:][:space:]]+)Curve", 
           "Curve Color:[[:space:]]+([[:alnum:][:blank:]]+)"))[,2] %>% 
    trimws() -> found 

    df <- read.table(text=found[2], skip=2, col.names=c("index", "variable.1", "variable.2")) 
    df$curve.name <- found[1] 
    df$color <- found[3] 
    df 

}) 
## index variable.1 variable.2 curve.name color 
## 1  0   30  100 Curve A Blue 
## 2  1   40   95 Curve A Blue 
## 3  2   50   90 Curve A Blue 
## 4  0   30  100 Curve B Green 
## 5  1   40   90 Curve B Green 
## 6  2   50   80 Curve B Green 
+0

很好的解決方案。 @hrbrmstr爲什麼你在'stringi :: stri_trim_both'上使用'trimws'? – Rentrop

+1

23:30EST :-)我會責怪它的簡潔性 – hrbrmstr

相關問題