Обработка заблокированных данных в R - PullRequest
0 голосов
/ 14 мая 2018

У меня есть большой текстовый файл (находится здесь https://www.dropbox.com/s/k2jqbpgtxw7d66m/test.txt?dl=0) на данных о почве из базы данных WISE, который немного запутан, и мне нужно извлечь из него некоторую информацию.

Текстовый файлорганизован в виде групп, которые разделены пустой строкой, и каждая группа имеет ту же структуру, как показано на рисунке ниже:

*WI_CLAF001  WISE        L       150 WISE DATABASE, SOIL AF001
@SITE        COUNTRY          LAT     LONG SCS Family
 -99         Afganistan    34.500   69.167 Luvic Calcisol (CLl)
@ SCOM  SALB  SLU1  SLDR  SLRO  SLNF  SLPF  SMHB  SMPX  SMKE
    BN  0.13  9.60  0.60 75.00  1.00  1.00 SA001 SA001 SA001
@  SLB  SLMH  SLLL  SDUL  SSAT  SRGF  SSKS  SBDM  SLOC  SLCL  SLSI  SLCF  SLNI  SLHW  SLHB  SCEC  SADC
    15     - 0.129 0.283 0.459  1.00  1.56  1.35  0.76 20.00 40.00 20.00  0.06  7.90 -99.0 -99.0 -99.0
    60     - 0.184 0.327 0.466  0.47  0.69  1.37  0.23 35.00 55.00 -99.0  0.03  7.90 -99.0 -99.0 -99.0
   150     - 0.178 0.311 0.461  0.12  0.87  1.39  0.09 35.00 55.00 -99.0  0.03  7.90 -99.0 -99.0 -99.0
@  SLB  SLPX  SLPT  SLPO CACO3  SLAL  SLFE  SLMN  SLBS  SLPA  SLPB  SLKE  SLMG  SLNA  SLSU  SLEC  SLCA
    15 -99.0 -99.0 -99.0   9.3 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0   0.4 -99.0
    60 -99.0 -99.0 -99.0  17.7 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0   0.3 -99.0
   150 -99.0 -99.0 -99.0  18.2 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0   0.3 -99.0

*WI_FLAF002  WISE        L       170 WISE DATABASE, SOIL AF002
@SITE        COUNTRY          LAT     LONG SCS Family
 -99         Afganistan    34.500   69.000 Calcaric Fluvisol (FLc)
@ SCOM  SALB  SLU1  SLDR  SLRO  SLNF  SLPF  SMHB  SMPX  SMKE
    BN  0.13  9.60  0.25 75.00  1.00  1.00 SA001 SA001 SA001
@  SLB  SLMH  SLLL  SDUL  SSAT  SRGF  SSKS  SBDM  SLOC  SLCL  SLSI  SLCF  SLNI  SLHW  SLHB  SCEC  SADC
    20     - 0.136 0.312 0.477  0.82  1.17  1.29  1.28 20.00 40.00 -99.0  0.09  8.50 -99.0 -99.0 -99.0
    60     - 0.110 0.235 0.502  0.45  4.84  1.24  0.60 20.00 65.00 -99.0  0.06  8.60 -99.0 -99.0 -99.0
   110     - 0.210 0.344 0.472  0.18  0.53  1.35  0.39 35.00 55.00 -99.0  0.06  8.50 -99.0 -99.0 -99.0
   170     - 0.115 0.268 0.441  0.06  1.68  1.41  0.27 20.00 40.00 -99.0  0.03  8.80 -99.0 -99.0 -99.0
@  SLB  SLPX  SLPT  SLPO CACO3  SLAL  SLFE  SLMN  SLBS  SLPA  SLPB  SLKE  SLMG  SLNA  SLSU  SLEC  SLCA
    20 -99.0 -99.0 -99.0  19.1 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0   0.4 -99.0
    60 -99.0 -99.0 -99.0  19.2 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0   0.3 -99.0
   110 -99.0 -99.0 -99.0  20.3 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0   0.3 -99.0
   170 -99.0 -99.0 -99.0  24.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0   0.3 -99.0

*WI_FLAF003  WISE        L       110 WISE DATABASE, SOIL AF003
@SITE        COUNTRY          LAT     LONG SCS Family
 -99         Afganistan    34.500   69.167 Calcaric Fluvisol (FLc)
@ SCOM  SALB  SLU1  SLDR  SLRO  SLNF  SLPF  SMHB  SMPX  SMKE
    BN  0.13  9.60  0.05 75.00  1.00  1.00 SA001 SA001 SA001
@  SLB  SLMH  SLLL  SDUL  SSAT  SRGF  SSKS  SBDM  SLOC  SLCL  SLSI  SLCF  SLNI  SLHW  SLHB  SCEC  SADC
    20     A 0.106 0.276 0.453  0.82  1.66  1.37  0.59 20.00 40.00 -99.0  0.07  8.80 -99.0 -99.0 -99.0
    50    Bg 0.135 0.238 0.404  0.50  2.14  1.49  0.24 10.00 25.00 -99.0  0.04  9.20 -99.0 -99.0 -99.0
   110    Cg 0.081 0.214 0.428  0.20  3.86  1.46 -99.0 25.00 15.00 -99.0 -99.0  8.90 -99.0 -99.0 -99.0
@  SLB  SLPX  SLPT  SLPO CACO3  SLAL  SLFE  SLMN  SLBS  SLPA  SLPB  SLKE  SLMG  SLNA  SLSU  SLEC  SLCA
    20 -99.0 -99.0 -99.0  16.9 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0   1.9 -99.0
    50 -99.0 -99.0 -99.0  13.8 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0   0.6 -99.0
   110 -99.0 -99.0 -99.0  19.6 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0 -99.0   0.4 -99.0

Строка 1: * WI _... содержит некоторые детали. Неполезно для меня

ROW 2: содержит заголовки, такие как название страны, лат, long

ROW 3: содержит данные для этих заголовков

Row 4: другой набор заголовков

Строка 5: содержит данные для заголовков в строке 4

Строка 6: содержит заголовки

Строка 7: 9: содержит данные для строки 6

Строка 10: является продолжением заголовков строки 6

строки 11:13: содержит данные для строки 10

Проблема заключается в том, что при переходе к какой-либо другой группе данных (другой стране)изменить количество строк в строке 6

Я пытаюсь сделать две вещи для каждой группы:

1) иметь отдельный кадр данных для строки 2 до строки 5, который должен выглядеть следующим образом:

  COUNTRY   LAT LONG SCS Family SCOM SALB SLU1 SLDR SLRO SLNF SLPF SMHB SMPX SMKE 
  Afghanistan
  Afghanistan
  Afghanistan
  .
  .
  .
  Argentina
  Argentina
  Argentina
  .
  .
  .

2) отдельный кадр данных для строки 6 до строки N

  COUNTRY     LAT       LONG    SLB  SLMH  SLLL  SDUL  SSAT  SRGF  SSKS  SBDM  SLOC  SLCL  SLSI  SLCF  SLNI  SLHW  SLHB  SCEC  SADC  SLPX  SLPT  SLPO CACO3  SLAL  SLFE  SLMN  SLBS  SLPA  SLPB  SLKE  SLMG  SLNA  SLSU  SLEC  SLCA
  Afganistan  34.500   69.167   15
  Afganistan  34.500   69.167   60
  Afganistan  34.500   69.167   150

Iраньше я не обрабатывал такие типы данных, но вот некоторые из моих логических приемов:

Для 1) я мог бы прочитать данные:

  dat <- readLines("dat.txt")

удалитьстроки, в которых есть "Мудрость".Это лишняя строка, затем разделите данные на список, используя пустое пространство
R, разделите текст на пустую строку

Для каждого элемента (группы) списка: возьмите строку 2- 5 и конвертировать в желаемый формат.

Не уверен, что мне делать со строкой 6 для второй части вопроса.

Буду признателен за помощь.Большое спасибо.

1 Ответ

0 голосов
/ 14 мая 2018

Я скопировал текст, вставленный вместо вашего изображения, в именованную символьную переменную txt, затем:

tL <- readLines(textConnection(txt))
Site_lines=grep("@SITE",tL)
Site_lines
#[1]  2 16 32
lapply( Site_lines , function(L) read.table(text= tL, header=TRUE, skip=L-1, nrow=1) )
#-----------------------
[[1]]
        X.SITE COUNTRY    LAT  LONG      SCS Family
-99 Afganistan    34.5 69.167 Luvic Calcisol  (CLl)

[[2]]
        X.SITE COUNTRY LAT     LONG      SCS Family
-99 Afganistan    34.5  69 Calcaric Fluvisol  (FLc)

[[3]]
        X.SITE COUNTRY    LAT     LONG      SCS Family
-99 Afganistan    34.5 69.167 Calcaric Fluvisol  (FLc)
# ------- now something that can pull them together ---------
do.call("rbind", lapply( Site_lines , function(L) read.table(text= tL, header=TRUE, skip=L-1, nrow=1) ) )

         X.SITE COUNTRY    LAT     LONG      SCS Family
-99  Afganistan    34.5 69.167    Luvic Calcisol  (CLl)
-991 Afganistan    34.5 69.000 Calcaric Fluvisol  (FLc)
-992 Afganistan    34.5 69.167 Calcaric Fluvisol  (FLc)

К сожалению, эта таблица не является регулярной, как может показаться на первый взгляд.Если вы посмотрите на расстояние между позициями "@SITE" в полном файле (с его почти 60 000 строк), вы получите:

table(diff(Site_lines))

 10  12  14  16  18  20  22  24  26 
 47 156 526 664 797 906 169  85  53 

И пытаетесь использовать lapply(, ... read.table подход вызывает ошибку.Возможно, вам придется использовать for -loop с try.Первая ошибка была в строке 6070:

counter <- 0
do.call("rbind", lapply( Site_lines , function(L) { counter <<- L; read.table(text= tL, header=TRUE, skip=L-1, nrow=1) }))
Error in read.table(text = tL, header = TRUE, skip = L - 1, nrow = 1) : 
  more columns than column names
> counter
[1] 6070
...