Переименование имени переменной в списке в R - PullRequest
0 голосов
/ 28 августа 2018

Считай, у меня есть список:

 >li

 $`first`
 [1] "Hello"

 $test
 [1] 3 4 5

Я пытался изменить значение 'first' командой ниже:

names(li["first"]) ="sign"

Но это не изменило имя переменной. Может кто-нибудь сказать мне, почему он не изменился или как работает этот код?

Считай, список большой. Я хотел бы знать, как изменить имена переменных без индексации.

Ответы [ 3 ]

0 голосов
/ 28 августа 2018

Используя ваш пример:

li <- list(first = c("Hello"), test = c(3, 4, 5))

Мы можем напрямую вызвать первый элемент в списке с помощью [1] и переименовать его с помощью «знака» (что вам и нужно).

names(li)[1] <- "sign"
0 голосов
/ 28 августа 2018

Ваш код не работает, потому что когда вы делаете names(li["first"]) = "sign", вы делаете:

  1. li["first"] - Извлечение подсписка из списка. Это создает новый список.
  2. names(li["first"]) - Получение имен подсписка, а не исходного списка.
  3. names(li["first"]) = "sign" - присвоение нового имени "sign" одному члену подсписка. Исходный список li не имеет к этому никакого отношения, он был потерян для инструкции в тот момент, когда вы извлекли список. При выходе из функции 'names<-' подсписок теряется, новый подсписок существует только в среде функции 'names<-'.

И это абсолютно общее, не только для списков. Если вы хотите изменить атрибут names объекта R, вы должны сначала получить значение этого атрибута и указать в нем names, а не объект. При поднаборе объекта вы создаете новый; при задании атрибута вы сохраняете объект без изменений.

Если вы не знаете порядковый номер члена списка, чье имя вы хотите изменить, правильный путь - в комментарии @Ronak Shah. И если вы хотите изменить несколько имен одновременно, используйте %in% вместо ==.

# Ronak Shah's comment
names(li)[names(li) == "first"] <- "sign"
names(li)
#[1] "sign" "test"

# To change 2 names use `%in%`
li2 <- list(first = "Hello", test = 3:5, second = letters[1:5])
names(li2)[names(li2) %in% c("first", "second")] <- paste("sign", 1:2, sep = "_")
names(li2)
#[1] "sign_1" "test"   "sign_2"

Редактировать.

После комментария пользователя Mikko Marttila я решил объяснить это более точно.

Я думаю, что это хорошая разбивка типа "эвристики" понимаю, что происходит, но это не совсем точно, что на самом деле случается. Расширение функций замены в names(li["first"]) = "sign" в конечном итоге эквивалентно делать

li <- "[<-"(li, "first", value = "names<-"(li["first"], value = "sign"))  

Обычно это различие не имеет значения, но если, например, li["first"] имеет класс с плохим поведением 'names<-'() метод вы против сюрприз.

Неправильный путь.
Давайте разберем инструкцию в комментарии по частям.
Он начинается с извлечения списка из списка li.

sub_li <- `[`(x = li, i = "first")
sub_li
#$`first`
#[1] "Hello"

Затем он устанавливает новое имя для одного из участников этого подсписка (единственный, "first").

sub_li <- `names<-`(x = sub_li, value = "sign")
sub_li 
#$`sign`
#[1] "Hello"

Затем присваивается значение подсписка sub_li члену li, члену "first".

li <- `[<-`(li, "first", value = sub_li)
#li
#$`first`
#[1] "Hello"
#
#$test
#[1] 3 4 5

Теперь, видимо, li не изменился. Но это так, новое значение - "Hello". Это не вина R, если старые и новые значения равны, R сделал то, что ему было поручено.
Чтобы доказать, что что-то произошло, я изменю значение sub_li["sign"] и выполню точно такую ​​же инструкцию.

sub_li["sign"] <- "Goodbye"

li <- `[<-`(li, "first", value = sub_li)
li
#$`first`
#[1] "Goodbye"
#
#$test
#[1] 3 4 5

См? R не глючил. Ошибка в том, что это не то, что задумал программист.

Правильный путь.
Правильный путь намного проще. Начните с создания исходного списка li.

li <- list(first = c("Hello"), test = c(3, 4, 5))

Код, который работает выше (код Ронака): names(li)[names(li) == "first"] <- "sign". Забывая логический индекс и используя индексный номер 1, это разбивается на две инструкции.
Первое - это присвоение '[<-'(x, i, values).

stuff <- `[<-`(x = names(li), i = 1, values = "sign")

Вторым является присвоение новых значений атрибуту names.

`names<-`(x = li, value = stuff)
#$`sign`
#[1] "Hello"
#
#$test
#[1] 3 4 5

Выполняется однострочник R

li <- `names<-`(x = li, value = `[<-`(x = names(li), i = 1, values = "sign"))

li
#$`sign`
#[1] "Hello"
#
#$test
#[1] 3 4 5

Вот и все.

0 голосов
/ 28 августа 2018

Я хотел бы знать, как изменить имена переменных без индексирование.

Вы должны назначить новый вектор, который содержит новые имена.

names(li) =c("sign","test")

и результат:

> names(l)
[1] "sign" "test"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...