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'