Как прочитать этот файл в R

У меня есть следующий файл:

GroupA Whatever1 A B C
GroupB Whatever2 C D
GroupC Whatever3 E F G H

Столбцы 1 и 2 следует читать как отдельные столбцы. Остаток каждой строки не должен быть разбит на табуляции и должен составлять третий столбец. Вот один уродливый способ сделать это:

foo <- read.table( text="GroupA Whatever1 A B C
GroupB Whatever2 C D
GroupC Whatever3 E F G H", fill=T, header=F)
foo2 <- data.frame( foo$V1, foo$V2, 
  V3=apply( foo[,-c(1,2)], 1, 
    function(x) paste0( x, collapse="\t")))

В результате получилось то, что я хотел бы иметь:

> foo2
  foo.V1    foo.V2         V3
1 GroupA Whatever1  A\tB\tC\t
2 GroupB Whatever2   C\tD\t\t
3 GroupC Whatever3 E\tF\tG\tH

Есть ли способ лучше? Предпочтительно тот, который не требует сначала разделить, а затем снова вставить столбцы? Некоторые из этих строк в таблице очень и очень длинные.


person January    schedule 13.05.2015    source источник
comment
В исходном файле есть разделители или просто пробелы? Кроме того, есть ли пробелы внутри первых двух столбцов?   -  person A5C1D2H2I1M1N2O1R2T1    schedule 14.05.2015


Ответы (3)


Может с тидыр...?

> library(tidyr)
> unite(foo,foo_all,V3:V6,sep = "\t")
      V1        V2    foo_all
1 GroupA Whatever1  A\tB\tC\t
2 GroupB Whatever2   C\tD\t\t
3 GroupC Whatever3 E\tF\tG\tH
person joran    schedule 13.05.2015
comment
Недостатком этого является то, что мне все еще нужно прочитать файл foo, без необходимости разбивая остатки строки на столбцы. Файл огромен, а некоторые строки очень длинные (тысячи имен, разделенных табуляцией), поэтому read.table создает фрейм данных с тысячами столбцов, в основном пустых. - person January; 14.05.2015
comment
@January Просто мысли вслух ... возможно, прочитайте группы столбцов отдельно, используя fread в data.table. - person joran; 14.05.2015
comment
@January ... в более широком смысле кажется, что функции ввода файлов readr и data.table нацелены на обычные табличные данные. Но они оба очень быстрые. Может быть не так уж много штрафа за чтение полного файла с помощью одного из этих инструментов, а затем его свертывание в памяти. - person joran; 14.05.2015
comment
@joran, fread не будет читать неправильные (непрямоугольные) данные. Нет эквивалента fill = TRUE из read.table. - person A5C1D2H2I1M1N2O1R2T1; 14.05.2015
comment
На данный момент я решил это, прочитав без разделителя (все в один столбец) и используя gsub для разделения строк на три столбца. - person January; 14.05.2015

Я бы рассмотрел функцию разделения строк, которая позволяет указать количество результирующих фрагментов. Например, вы можете использовать stri_split_fixed из пакета "stringi".

Здесь я предполагаю, что вы использовали readLines для получения текста из вашего файла:

text <- c("GroupA Whatever1 A B C", 
          "GroupB Whatever2 C D", 
          "GroupC Whatever3 E F G H")

library(stringi)

stri_split_fixed(text, " ", 3, simplify = TRUE)
#      [,1]     [,2]        [,3]     
# [1,] "GroupA" "Whatever1" "A B C"  
# [2,] "GroupB" "Whatever2" "C D"    
# [3,] "GroupC" "Whatever3" "E F G H"

Отсюда, если вы действительно хотите заменить пробелы табуляцией в последнем столбце, это должно быть очень простой операцией gsub.

person A5C1D2H2I1M1N2O1R2T1    schedule 14.05.2015

Почему бы не манипулировать вашим набором данных из командной строки с помощью awk? (или другой язык, такой как python, perl и т. д.)

Вот решение с awk. Сначала вам нужно узнать максимальное количество столбцов вашего набора данных:

foo=$(awk "BEGIN{max=0} {if(NF>max) max=NF} END{print max}" dataset_file_name)

Теперь можно использовать awk-скрипт, передав ему только что вычисленный нами параметр и перенаправив вывод в новый файл:

awk -f my_script.awk -v max=$foo dataset_file_name > my_new_dataset

В R вы должны указать разделитель (пробел):

bar <- read.table("my_new_dataset", sep=" ")

И вы получите тот же результат, что и в приведенном вами примере.


Вот код my_script.awk:

{
  printf("%s %s ", $1, $2);
  for(i=3; i<NF; i++) printf("%s/t", $i);
  printf("%s", $NF)
  if(NF<max)
    for(i=1; i<(max=1-NF); i++) printf("\t");
  printf("\n");
}

Другим возможным решением может быть разделение файла набора данных на два отдельных файла: первый с первыми двумя столбцами, а второй — со всеми остальными столбцами. Таким образом, возможно, вам будет проще импортировать и манипулировать третьим столбцом вашего набора данных.

В командной строке:

cut -f -2 dataset_file_name > dataset_columns_1_2
cut -f 3- dataset_file_name > dataset_rest_of_columns

[Примечание: разделителем для cut является табуляция, если разделитель столбцов отличается, используйте параметр -d (для получения дополнительной информации cut --help).]

На самом деле я не вижу никакого реального преимущества в использовании этого подхода... но я думаю, что команда cut могла бы быть полезна в некоторых других случаях.

person LikosX    schedule 15.05.2015