Разделение столбцов в CSV-файле [дубликат]

for i in xrange(len(somelist) - 1, -1, -1):
    if some_condition(somelist, i):
        del somelist[i]

Вам нужно вернуться назад, иначе это немного похоже на распиливание ветви дерева, на которой вы сидите: -)

7
задан Josh O'Brien 9 May 2014 в 16:55
поделиться

3 ответа

Я бы это сделал.

read.table(textConnection(gsub(",", "\t", readLines("file.txt"))))
  V1 V2 V3 V4 V5
1  a  1  2  3  5
2  b  4  5  6  7
3  c  5  6  7  8

Распаковывая это немного:

  • readLines() считывает файл в R в виде символьного вектора с одним элемент для каждой строки.
  • gsub(",", "\t", ...) заменяет каждую запятую на вкладку, так что теперь у нас есть строки только с одним видом разделительного символа.
  • textConnection() завершает символьный вектор (модифицированных) строк файла, чтобы они отображались как файл в read.table(), так что ...
  • read.table может обращаться к ним, как к обычному файлу.

.

18
ответ дан Josh O'Brien 25 August 2018 в 13:59
поделиться

«Сбалансированные» данные

Судя по тому, как вы сформулировали свой вопрос, кажется, что вы знаете, что ваши данные «сбалансированы» (прямоугольные).

Вы ищет более быстрые варианты? Возможно, вы захотите объединить fread с «data.table» с моей экспериментальной функцией concat.split.DT .

Решение будет выглядеть примерно так: (замените " " на "\t" для вкладки:

concat.split.DT(fread("yourfile.txt", sep = " ", header=FALSE), "V2", ",")

Давайте создадим некоторые данные:

x <- c("a\t1,2,3,5", "b\t4,5,6,7","c\t5,6,7,8")
X <- c(replicate(10000, x))
temp <- tempfile()
writeLines(X, temp, sep="\n") ## Write it to a temporary file

Ответ Джоша:

system.time(out1 <- read.table(text = gsub(",", "\t", readLines(temp))))
#    user  system elapsed 
#   0.679   0.000   0.676 
head(out1)
#   V1 V2 V3 V4 V5
# 1  a  1  2  3  5
# 2  b  4  5  6  7
# 3  c  5  6  7  8
# 4  a  1  2  3  5
# 5  b  4  5  6  7
# 6  c  5  6  7  8
dim(out1)
# [1] 30000     5

fread + concat.split.DT (что похоже на использование fread дважды, но все же супер быстро):

system.time(out2 <- concat.split.DT(fread(temp, sep = "\t", header=FALSE), "V2", ","))
#    user  system elapsed 
#   0.027   0.000   0.028 
head(out2)
#    V1 V2_1 V2_2 V2_3 V2_4
# 1:  a    1    2    3    5
# 2:  b    4    5    6    7
# 3:  c    5    6    7    8
# 4:  a    1    2    3    5
# 5:  b    4    5    6    7
# 6:  c    5    6    7    8
dim(out2)
# [1] 30000     5

«Несбалансированные» данные

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

Одно из ограничений вышеизложенного заключается в том, что concat.split.DT обрабатывает только «сбалансированные» данные. fread не имеет аргумента fill, например read.table (и, кажется, я помню, как читал где-то, что он скорее всего не будет иметь такого аргумента).

Вот пример того, что Я имею в виду неуравновешенный:

x2 <- c("a\t1,2,3,5,6,7", "b\t4,5,6,7","c\t5,6,7,8,9,10,11,12,13")
X2 <- c(replicate(10000, x2))
temp2 <- tempfile()
writeLines(X2, temp2, sep="\n")

read.table может обрабатывать это с аргументом fill = TRUE:

system.time(out1b <- read.table(text = gsub(",", "\t", readLines(temp2)), fill=TRUE))
#    user  system elapsed 
#   1.151   0.000   1.152 
head(out1b)
#   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
# 1  a  1  2  3  5  6  7 NA NA  NA
# 2  b  4  5  6  7 NA NA NA NA  NA
# 3  c  5  6  7  8  9 10 11 12  13
# 4  a  1  2  3  5  6  7 NA NA  NA
# 5  b  4  5  6  7 NA NA NA NA  NA
# 6  c  5  6  7  8  9 10 11 12  13

concat.split.DT даст вам неприятную ошибку в таких случаях , но вы можете попробовать мою функцию cSplit . Это не так быстро, но по-прежнему выполняется прилично:

system.time(out2b <- cSplit(fread(temp2, sep = "\t", header=FALSE), "V2", ","))
#    user  system elapsed 
#   0.393   0.004   0.399 
head(out2b)
#    V1 V2_1 V2_2 V2_3 V2_4 V2_5 V2_6 V2_7 V2_8 V2_9
# 1:  a    1    2    3    5    6    7   NA   NA   NA
# 2:  b    4    5    6    7   NA   NA   NA   NA   NA
# 3:  c    5    6    7    8    9   10   11   12   13
# 4:  a    1    2    3    5    6    7   NA   NA   NA
# 5:  b    4    5    6    7   NA   NA   NA   NA   NA
# 6:  c    5    6    7    8    9   10   11   12   13
8
ответ дан A5C1D2H2I1M1N2O1R2T1 25 August 2018 в 13:59
поделиться
Scanner scan = new Scanner(file);
while (scan.hasNextLine()) {
    String[] a = scan.nextLine().replace("\\t", ",").split(",");
    //do something with the array
}
scan.close();

Это сделало:

  1. создать сканер для обработки файла (сканирование сканера)
  2. сканирования в следующей строке файла (scan.nextLine ()) для каждой строки файла на основе hasNextLine ()
  3. заменены вкладки запятыми (.replace ("\ t", ",")), поэтому разделители были одинаковыми
  4. split в массив через запятую. Теперь вы можете обрабатывать все данные одинаково независимо от длины каждой строки.
  5. Не забудьте закрыть сканер, когда закончите.
0
ответ дан La-comadreja 25 August 2018 в 13:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: