R - ошибка: "дубликаты" row.names "не допускаются"

Я знаю, что это постоянный вопрос, поэтому заранее прошу прощения за кросс-постинг.

У меня проблемы с чтением вывода модели .csv файл, который выглядит примерно так (исходный файл имеет около 14 000 строк, но столбцы выглядят так, как здесь):

time    x     y       z          w      r         s         t
1980    1   0.8327  0.3402    0.2021    0       1.1729      0
1980    2   0.7886  0.3399    0.2019    0       2.3014      0
1980    3   0.7909  0.3396    0.2017    0       3.4319      0
1980    4   0.7846  0.3394    0.2016    0       4.5559      0
1980    5   0.8103  0.3392    0.2014    0       5.7053      0
1980    6   0.8207  0.339     0.2013    0       6.865       0
1980    7   0.8263  0.3388    0.2012    0       8.0301      0
1980    14  0.9112  10.3411   20.6821   3.1175  60.4644     3.1175
1980    15  0.9092  8.878     17.756    2.734   70.2517     5.8515
1980    16  0.9001  9.5232    19.0464   2.9655  80.6749     8.817
1980    17  1.0313  7.59      15.18     2.4332  89.2962     11.2502
1980    18  1.0333  6.8859    13.7718   2.266   97.2154     13.5162

Для команды:

read.csv("df", header = TRUE, sep = ",", blank.lines.skip = FALSE)

Я получаю следующее сообщение об ошибке:

Error in read.table(file = file, header = header, sep = sep, quote = quote,  : 
  duplicate 'row.names' are not allowed

Из того, что я понял из ответов на подобные вопросы, возможной проблемой может быть то, что read.csv Команда не распознает нули в последнем столбце как значения, поэтому программа считывает их так, как если бы первая строка содержала на одно поле меньше, чем число столбцов, и, следовательно, использует первый столбец для имен строк.

Однако, когда я создаю "фальшивую" таблицу с фактическими нулями, пробелами или "NA" в тех же позициях, как показано в примере выше, программа без проблем распознает их и прочитает файл.

например

df <- data.frame(x=c(1,2,3,3,3,4,5,2,2,6,7,3,8,9,10))
df$y <- c(4,8,9,1,1,5,8,8,3,2,0,9,4,4,7)
df$z <- c(" "," "," ",4,5,6,7,8,9,10,11,12,13,14,15)
OR:
df$z <- c(0,0,0,4,5,6,7,8,9,10,11,12,13,14,15)
OR:
df$z <- c("NA","NA","NA",4,5,6,7,8,9,10,11,12,13,14,15)

Кто-нибудь может сказать мне, почему это происходит?

Я решил проблему, как предложили другие пользователи:

df <- read.csv("df.csv", header = TRUE, row.names = NULL)
colnames(df) <- c(colnames(df)[-1],NULL)
write.table(df, "df.csv", sep = ",", col.names = TRUE, row.names = FALSE)

And start working as normal from here.

Это работает просто отлично, но мне было интересно, есть ли более прямое решение этой проблемы или есть что-то, чего мне не хватает.

Спасибо,

3 ответа

Вот два способа.

Первый использует внешний пакет, data.table, функция fread делает работу с предупреждением. И имена столбцов перепутаны, так как первая строка имеет меньше полей, чем другие строки, fread отбрасывает этот ряд.

data.table::fread("test.csv", sep = ";")
#   V1 V2 V3
#1:  A  1  6
#2:  A  2  7
#3:  A  3  8
#4:  A  4  9
#5:  A  5 10

Предупреждающее сообщение:
В data.table::fread("test2.csv", sep = ";"):
Начало ввода данных в строке 2 и удаление строки 1, потому что она имеет слишком
мало или слишком много элементов, чтобы быть именами столбцов или данными: Col1;Col2

Второй способ сложнее. Если вы не хотите загружать дополнительный пакет, я написал функцию, которая использует readLines читать в первой строке с именами столбцов, а затем читает остальную часть файла с read.table,

myread <- function(file, sep = ",", ...){
    nm <- readLines(file, n = 1)
    nm <- unlist(strsplit(nm, sep))
    DF <- read.table(file, skip = 1, sep = sep, ...)
    if(length(names(DF)) > length(nm)){
        names(DF)[(length(names(DF)) - length(nm) + 1):length(names(DF))] <- nm
    } else names(DF) <- nm
    DF
}

myread("test.csv", sep = ";")
#  V1 Col1 Col2
#1  A    1    6
#2  A    2    7
#3  A    3    8
#4  A    4    9
#5  A    5   10

ФАЙЛ

Вот содержимое файла. Обратите внимание, что разделитель столбцов - это точка с запятой. В большинстве стран континентальной Европы мы используем запятую в качестве маркера десятичной дроби, поэтому формат CSV разделяет столбцы точкой с запятой.

Col1;Col2
A;1;6
A;2;7
A;3;8
A;4;9
A;5;10

Со страницы справки для read.csv:

Если имеется заголовок и первая строка содержит на одно поле меньше, чем количество столбцов, первый столбец во входных данных используется для имен строк. В противном случае, если 'row.names' отсутствует, строки нумеруются.

Не видя CSV, трудно сказать, но, похоже, он должен соответствовать перечисленным критериям (т. Е. В первой строке меньше записей, возможно, из-за пустого имени столбца).

моя проблема с 'row.names' заключалась в том, что я просто использовал неправильный 'sep'

Другие вопросы по тегам