Пропускать метаданные при импорте набора данных в R

Мой вопрос касается того, как пропустить метаданные в начале файла при импорте данных в R. Мои данные имеют формат .txt, где первые строки представляют собой метаданные, описывающие данные, и их необходимо отфильтровать. Ниже приведен минимальный пример фрейма данных в формате с разделителями табуляции:

Type=GenePix Export                         
DateTime=2010/03/04 16:04:16                        
PixelSize=10                        
Wavelengths=635                     
ImageFiles=Not Saved                        
NormalizationMethod=None                        
NormalizationFactors=1                      
JpegImage=                      
StdDev=Type 1                       
FeatureType=Circular                        
Barcode=                        
BackgroundSubtraction=LocalFeature                      
ImageOrigin=150, 10                     
JpegOrigin=150, 2760                        
Creator=GenePix Pro 7.2.29.002                      
var1    var2    var3    var4    var5    var6    var7
1   1   1   molecule1   1F3 400 4020
1   2   1   molecule2   1B5 221 4020
1   3   1   molecule3   1H5 122 2110
1   4   1   molecule4   1D1 402 2110
1   5   1   molecule5   1F1 600 4020

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

mydata <- read.table("mydata.txt",header=T, skip=15)

Который вернется;

mydata
  var1 var2 var3      var4 var5 var6 var7
1    1    1    1 molecule1  1F3  400 4020
2    1    2    1 molecule2  1B5  221 4020
3    1    3    1 molecule3  1H5  122 2110
4    1    4    1 molecule4  1D1  402 2110
5    1    5    1 molecule5  1F1  600 4020

Проблема в том, что мне нужно написать сценарий, который может читать различные наборы данных, где номер строки, с которой начинаются фактические данные, варьируется от одного набора данных к другому. Я мог бы представить себе использование чего-то вроде пакета sqldf, но я не совсем знаком с sql.

Будем очень благодарны любой помощи.


person amo    schedule 16.03.2015    source источник
comment
Определили ли вы, что будет определять точку разделения между метаданными и фактическими данными (это должно работать для всех наборов данных; например, данные могут использовать таблицы для разделителей полей, а в метаданных вообще нет таблиц)?   -  person Dominic Comtois    schedule 16.03.2015
comment
@amo У вас есть какие-то определенные шаблоны, с которых начинаются имена столбцов?   -  person akrun    schedule 16.03.2015
comment
Да, одна точка разделения между метаданными и фактическими данными заключается в том, что данные используют вкладки для разделителей полей, а в метаданных никогда нет вкладок, и это работает для всех наборов данных @DominicComtois   -  person amo    schedule 16.03.2015
comment
Да, существует определенный шаблон, в котором имена столбцов начинаются, например, var1, и это работает для всех наборов данных @akrun.   -  person amo    schedule 16.03.2015
comment
@amo Спасибо, я обновил решение на основе этой информации.   -  person akrun    schedule 16.03.2015


Ответы (5)


Вы можете использовать count.fields() для определения аргумента skip. Я называю ваш файл "x.txt"

read.table("x.txt", skip = which.max(count.fields("x.txt") == 7) - 1, 
    header = TRUE)
#   var1 var2 var3      var4 var5 var6 var7
# 1    1    1    1 molecule1  1F3  400 4020
# 2    1    2    1 molecule2  1B5  221 4020
# 3    1    3    1 molecule3  1H5  122 2110
# 4    1    4    1 molecule4  1D1  402 2110
# 5    1    5    1 molecule5  1F1  600 4020

Таким образом, чтение файла начинается с первого появления семи полей.

person Rich Scriven    schedule 16.03.2015
comment
Почему бы не skip = which.max(count.fields("x.txt")) - 1, чтобы файл с 6, 8 или 12 колонками тоже работал? - person Dominic Comtois; 16.03.2015
comment
Да, я бы рассмотрел просто skip = which.max(count.fields("x.txt")) - 1 улучшение решения, так как оно обычно работает в разных случаях. @ДоминикКомтуа - person amo; 16.03.2015
comment
@amo И кстати, вы можете добавить sep="\t" в качестве аргумента к count.fields, чтобы быть еще более тщательным. - person Dominic Comtois; 16.03.2015

Как насчет использования уже существующих функций для чтения данных микрочипа ДНК? Они доступны в пакетах, разработанных проектом Bioconductor.

Например, примерно так

library(limma)

mydata<-read.maimages("mydata.txt", source="genepix")

Дополнительные примеры см. в руководстве по limma. . Он может легко импортировать большинство форматов ДНК-микрочипов.

person Community    schedule 16.03.2015
comment
Когда я попробовал этот код, используя входные данные, read.maimages('mydata.txt', source='genepix') #Error in readGPRHeader(fullname) : File is not in Axon Text File (ATF) format - person akrun; 16.03.2015

Комментарии к вашему вопросу описывают следующее:

  1. Раздел метаданных не содержит вкладок
  2. Раздел данных разделен табуляцией

Таким образом, я предполагаю, что ваши данные чем-то похожи на образец данных, приведенный в конце этого вопроса.

Если это так, вы можете использовать магию fread, чтобы автоматически определить, где начинаются ваши данные.

Вот демо:

cat(A, file = "mytest.txt", sep = "\n")
library(data.table)
fread("mytest.txt")
#    var1 var2 var3      var4 var5 var6 var7
# 1:    1    1    1 molecule1  1F3  400 4020
# 2:    1    2    1 molecule2  1B5  221 4020
# 3:    1    3    1 molecule3  1H5  122 2110
# 4:    1    4    1 molecule4  1D1  402 2110
# 5:    1    5    1 molecule5  1F1  600 4020

Пример данных:

A <- c("Type=GenePix Export", "DateTime=2010/03/04 16:04:16", "PixelSize=10", 
"Wavelengths=635", "ImageFiles=Not Saved", "NormalizationMethod=None", 
"NormalizationFactors=1", "JpegImage=", "StdDev=Type 1", "FeatureType=Circular", 
"Barcode=", "BackgroundSubtraction=LocalFeature", "ImageOrigin=150, 10", 
"JpegOrigin=150, 2760", "Creator=GenePix Pro 7.2.29.002", 
"var1\tvar2\tvar3\tvar4\tvar5\tvar6\tvar7", 
"1\t1\t1\tmolecule1\t1F3\t400\t4020", "1\t2\t1\tmolecule2\t1B5\t221\t4020", 
"1\t3\t1\tmolecule3\t1H5\t122\t2110", "1\t4\t1\tmolecule4\t1D1\t402\t2110", 
"1\t5\t1\tmolecule5\t1F1\t600\t4020")

A
#  [1] "Type=GenePix Export"               
#  [2] "DateTime=2010/03/04 16:04:16"      
#  [3] "PixelSize=10"                      
#  [4] "Wavelengths=635"                   
#  [5] "ImageFiles=Not Saved"              
#  [6] "NormalizationMethod=None"          
#  [7] "NormalizationFactors=1"            
#  [8] "JpegImage="                        
#  [9] "StdDev=Type 1"                     
# [10] "FeatureType=Circular"              
# [11] "Barcode="                          
# [12] "BackgroundSubtraction=LocalFeature"
# [13] "ImageOrigin=150, 10"               
# [14] "JpegOrigin=150, 2760"              
# [15] "Creator=GenePix Pro 7.2.29.002"    
# [16] "var1\tvar2\tvar3\tvar4\tvar5\tvar6\tvar7"
# [17] "1\t1\t1\tmolecule1\t1F3\t400\t4020"      
# [18] "1\t2\t1\tmolecule2\t1B5\t221\t4020"      
# [19] "1\t3\t1\tmolecule3\t1H5\t122\t2110"      
# [20] "1\t4\t1\tmolecule4\t1D1\t402\t2110"      
# [21] "1\t5\t1\tmolecule5\t1F1\t600\t4020"    
person A5C1D2H2I1M1N2O1R2T1    schedule 16.03.2015
comment
Решение, включающее fread("mytest.txt"), работает с набором данных, созданным путем преобразования исходного набора данных в другой формат с использованием cat(A, file = "mytest.txt", sep = "\n"), но не отфильтровывает метаданные в исходном наборе данных. @АнандаМахто - person amo; 16.03.2015
comment
@amo, вы всегда получите лучший ответ, если предоставите воспроизводимый пример. Простым способом сделать это было бы использовать что-то вроде dput(readLines("mytest.txt", n = 20)) (где mytest.txt следует заменить вашим фактическим именем файла), чтобы мы могли увидеть, как именно выглядят первые 20 строк вашего файла. При этом мы все можем использовать cat для воссоздания примера файла и тестирования наших решений. - person A5C1D2H2I1M1N2O1R2T1; 16.03.2015
comment
Процесс воссоздания демонстрационного файла отлично работает с минимальным набором данных, но это может оказаться сложной задачей для реального набора данных, который содержит ›3000 строк. @АнандаМахто - person amo; 16.03.2015
comment
@amo, я просто хотел сказать, что, поскольку вы не предоставили воспроизводимые образцы данных, я создал образцы данных, которые описывают то, что вы упомянули в своих комментариях: файл с метаданными, который не содержит вкладок, за которыми следуют табличные данные с каждым столбцом, разделенным символом вкладки. Я указал вам на fread, потому что fread легко справляется с такими проблемами, даже с наборами данных с миллионами строк. Жаль, что не получилось. Я предполагаю, что ваше описание проблемы было ошибочным. Я предполагаю, что в ваших метаданных есть вкладки. Вы можете легко проверить это, настроив текстовый редактор на отображение пробельных символов. - person A5C1D2H2I1M1N2O1R2T1; 16.03.2015

Предположим, что если все файлы имеют Creator в качестве последней строки метаданных,

read.table(pipe("awk 'NR ==1, /Creator/ {next}{print}' mydata.txt"),
              header=TRUE)
#  var1 var2 var3      var4 var5 var6 var7
#1    1    1    1 molecule1  1F3  400 4020
#2    1    2    1 molecule2  1B5  221 4020
#3    1    3    1 molecule3  1H5  122 2110
#4    1    4    1 molecule4  1D1  402 2110
#5    1    5    1 molecule5  1F1  600 4020

Если вы знаете количество столбцов, вы также можете сделать

read.table(pipe("awk 'NF==7{print}' mydata.txt"), header=TRUE)
#  var1 var2 var3      var4 var5 var6 var7
#1    1    1    1 molecule1  1F3  400 4020
#2    1    2    1 molecule2  1B5  221 4020
#3    1    3    1 molecule3  1H5  122 2110
#4    1    4    1 molecule4  1D1  402 2110
#5    1    5    1 molecule5  1F1  600 4020

Обновлять

Если нам нужно начать чтение с первого вхождения «var1» до конца файла,

  read.table(pipe("awk '/var1/ { matched = 1}matched { print }' mydata.txt"), 
             header=TRUE)    
 #   var1 var2 var3      var4 var5 var6 var7
 #1    1    1    1 molecule1  1F3  400 4020
 #2    1    2    1 molecule2  1B5  221 4020
 #3    1    3    1 molecule3  1H5  122 2110
 #4    1    4    1 molecule4  1D1  402 2110
 #5    1    5    1 molecule5  1F1  600 4020

Вышеупомянутые решения отлично работают в системе Linux. В Windows это не удалось (согласно комментариям). Вариант, который может работать в обеих системах,

 lines <- readLines('mydata.txt')
 read.table(text=lines[grep('var1', lines):length(lines)],header=TRUE)
 #   var1 var2 var3      var4 var5 var6 var7
 #1    1    1    1 molecule1  1F3  400 4020
 #2    1    2    1 molecule2  1B5  221 4020
 #3    1    3    1 molecule3  1H5  122 2110
 #4    1    4    1 molecule4  1D1  402 2110
 #5    1    5    1 molecule5  1F1  600 4020
person akrun    schedule 16.03.2015
comment
Символ в последней строке метаданных варьируется от одного набора данных к другому, поэтому первое решение может работать не во всех случаях. О двух других возможных решениях я получаю ошибки: Error in read.table(pipe("awk 'NF==7{print}' mydata.txt"), header = TRUE) : no lines available in input и Error in read.table(pipe("awk '/var1/ { matched = 1}matched { print }' mydata.txt"), : no lines available in input. Что может быть не так? @akrun - person amo; 16.03.2015
comment
@amo Я просто копировал/вставлял входные данные, показанные в сообщении, и сохранял их как mydata.txt. Итак, я не знаю, в чем может быть ошибка в вашем случае, так как это работает в моей системе. - person akrun; 16.03.2015
comment
@DominicComtois Я использую linux mint Но я думаю, что это может работать в Windows stackoverflow.com/questions/21927944/ - person akrun; 16.03.2015
comment
@amo Если я понимаю ваши комментарии, последние два решения получают ошибку. У вас есть проблема с первым кодом? (просто для любопытства) - person akrun; 16.03.2015
comment
На самом деле существует awk-версия для Windows, но ее нет по умолчанию, ее нужно установить с gnuwin32.sourceforge .net/packages/gawk.htm - person Dominic Comtois; 16.03.2015
comment
@DominicComtois Спасибо за ссылку. Я не так много использую окна, поэтому не знал, что это не сработает. - person akrun; 16.03.2015
comment
Да, у меня тоже проблема с первым решением @akrun - person amo; 16.03.2015
comment
У меня Windows 8. Судя по сайту установки gawk, версии gawk для Windows 8 нет @DominicComtois - person amo; 16.03.2015
comment
Хорошо... это объясняет, почему это решение не работает. Но, кажется, у вас есть много других очень хороших вариантов! - person Dominic Comtois; 16.03.2015
comment
@amo В любом случае, это будет вариант, если у вас есть возможность использовать систему Linux. - person akrun; 16.03.2015

Решение, основанное на наличии таблиц в реальных данных (а не в метаданных). В качестве «бонуса» у вас есть возможность отображать (через cat любые строки, которые считались метаданными).

Основная функция чтения

read.genepix <- function(filename, disp.meta = FALSE) {

    infile <- file(description = filename, open = "r" )

    # create a meta indicator function
    is.meta <- function(text) !grepl(pattern = "\\t", x = text)

    # Prepare to store meta text (if needed)
    meta.text <- c()
    meta <- TRUE

    while(isTRUE(meta)) {

        last.pos <- seek(infile, where = NA)
        current.line <- readLines(infile, n = 1)
        meta <- is.meta(current.line)

        if(isTRUE(meta)) {
            meta.text <- append(meta.text, current.line)
        } else {
            seek(infile, where = last.pos)
            data.txt <- paste0(readLines(infile),collapse="\n")
            close(infile)
            break
        }
    }

    if(isTRUE(disp.meta)) {
        cat(paste(meta.text, collapse="\n"))
    }

    return(read.table(text=data.txt, header = TRUE, sep = "\t", quote=""))
}

Использование/результаты

my.data <- read.genepix("somefile.txt")

my.data

#   var1 var2 var3      var4 var5 var6 var7
# 1    1    1    1 molecule1  1F3  400 4020
# 2    1    2    1 molecule2  1B5  221 4020
# 3    1    3    1 molecule3  1H5  122 2110
# 4    1    4    1 molecule4  1D1  402 2110
# 5    1    5    1 molecule5  1F1  600 4020

Пример данных, используемый в этом ответе (сохраненный на диске как "somefile.txt"), но обратите внимание, что SO заменяет табуляцию серией пробелов в разделе данных, поэтому в текстовом редакторе вам нужно будет замените эти пробелы таблицами, чтобы код работал.

capture.output(cat("Type=GenePix Export
DateTime=2010/03/04 16:04:16
PixelSize=10
Wavelengths=635
ImageFiles=Not Saved
NormalizationMethod=None
NormalizationFactors=1
JpegImage=
StdDev=Type 1
FeatureType=Circular
Barcode=
BackgroundSubtraction=LocalFeature
ImageOrigin=150, 10
JpegOrigin=150, 2760
Creator=GenePix Pro 7.2.29.002
var1    var2    var3    var4    var5    var6    var7
1   1   1   molecule1   1F3 400 4020
1   2   1   molecule2   1B5 221 4020
1   3   1   molecule3   1H5 122 2110
1   4   1   molecule4   1D1 402 2110
1   5   1   molecule5   1F1 600 4020
"), file="somefile.txt")
person Dominic Comtois    schedule 16.03.2015
comment
Функция read.genepix, кажется, печатает метаданные независимо от того, print.meta = TRUE) или print.meta = FALSE). Я предполагаю, что в функции есть небольшая ошибка. @ДоминикКомтуа - person amo; 16.03.2015
comment
Я обновил решение, чтобы файл читался только один раз; печать метаданных теперь также должна работать нормально. - person Dominic Comtois; 16.03.2015
comment
Проблема с печатью метаданных, даже когда print.meta = FALSE) все еще отображается @DominicComtois - person amo; 16.03.2015
comment
Я действительно не могу сказать, почему ... на моей машине этого не было. Я переименовал аргумент на случай, если он как-то связан с этим, и добавил более сильное условие; теперь он должен работать нормально. Если нет, убедитесь, что вы перезапустили сеанс перед повторным тестированием, пожалуйста! - person Dominic Comtois; 16.03.2015