Атрибут 'names' [21] должен иметь ту же длину, что и вектор [5]. Что это значит и почему я это получаю? - PullRequest
0 голосов
/ 10 октября 2019

При попытке переименовать столбцы я попробовал два подхода. Один работал, в то время как другой выдавал ошибку: -

     for(i in datalist)
   {
  print (i)
}

i=0:4
l1=list(1+5*i)
l1
l2=list(l1[[1]]+1)
l2
l3=list(l2[[1]]+1)
l3
l4=list(l3[[1]]+1)
l4
l5=list(l4[[1]]+1)
l5

df<-data.frame(a=l1,b=l2,c=l3,d=l4,e=l5)
df
for(i in 1:ncol(df))#Approach 1 which worked out successfully
  colnames(df)[i]=paste(c("x"),i,sep="")

for(i in df)#Approach 2 which threw an error
{
  colnames(df)[i]=paste(c("x"),i,sep="")
}

The correct output from approach 1-
x1 x2 x3 x4 x5
1  1  2  3  4  5
2  6  7  8  9 10
3 11 12 13 14 15
4 16 17 18 19 20
5 21 22 23 24 25

Ошибка при подходе 2 - Ошибка в именах (x) <- значение: атрибут 'names' [21] должен иметь ту же длину, что и вектор [5] </p>

Ответы [ 3 ]

2 голосов
/ 10 октября 2019

Синтаксис for (i in df) будет выполнять итерацию самих столбцов кадра данных. Но ваша первая версия, в которой выполняется итерация индекса числа столбцов, - это то, что вам нужно, поскольку вам необходим доступ к i-му столбцу фрейма данных.

Обратите внимание, что поскольку функция paste() векторизованаВы могли бы так же легко добиться желаемого, даже не используя цикл:

names(df) <- paste0("x", seq_along(df))
1 голос
/ 10 октября 2019

Мы на одной странице, я тоже учусь этому. У меня может не быть хорошего ответа. Но это то, что я хотел бы сделать, чтобы понять, что происходит.

Сначала я бы попытался понять, что означает i в вашем цикле.

k = 1
for(i in df ){
  print(paste("loop", k))
  print(i)
  k = k + 1
}

Вы получите:

[1] "loop 1"
[1]  1  6 11 16 21
[1] "loop 2"
[1]  2  7 12 17 22
[1] "loop 3"
[1]  3  8 13 18 23
[1] "loop 4"
[1]  4  9 14 19 24
[1] "loop 5"
[1]  5 10 15 20 25

Затем замените i в своем коде на loop 1 значения в виде вектора: c(1, 6, 11, 16, 21)

colnames(df)[c(1,  6, 11, 16, 21)] = paste(c("x"),c(1,  6, 11, 16, 21), sep = "")

тогда вы получите:

> colnames(df)[c(1,  6, 11, 16, 21)]=paste(c("x"),c(1,  6, 11, 16, 21),sep="")
Error in names(x) <- value : 
  'names' attribute [21] must be the same length as the vector [5]

Теперь мы знаем, откуда 21. Однако у вас нет 21 столбца, а у вас есть только 5 имен.

0 голосов
/ 10 октября 2019

Проблема вашего #Approach 2 заключается в том, что он перебирает значения в кадре данных по столбцам, а не по столбцам. Мы можем проверить это, распечатав значения

for(i in df) {
    print(i)
}

#[1]  1  6 11 16 21
#[1]  2  7 12 17 22
#[1]  3  8 13 18 23
#[1]  4  9 14 19 24
#[1]  5 10 15 20 25

Итак, на первой итерации вы делаете

colnames(df)[c(1, 6, 11, 16, 21)] = paste(c("x"),c(1, 6, 11, 16, 21),sep="")

, которая возвращает ту же ошибку, что и вы.

Ошибка в именах (x) <- значение: атрибут 'names' [21] должен иметь ту же длину, что и вектор [5] </p>

Ваш forцикл будет работать, если вы перебираете столбцы, как в первой попытке, или

for(i in seq_along(df)) {
   colnames(df)[i]=paste(c("x"),i,sep="")
}

Однако для переименования столбцов вам не нужно использовать цикл for, вы можете напрямую выполнить

names(df) <- paste0("x", seq_along(df))
#OR
#colnames(df) <- paste0("x", 1:ncol(df))
...