重命名R中列表中变量的名称

时间:2018-08-28 05:16:44

标签: r list

考虑一下我有一个列表:

 >li

 $`first`
 [1] "Hello"

 $test
 [1] 3 4 5

我试图通过以下命令更改“ first”的值:

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

但是它并没有改变变量的名称。 有人可以告诉我为什么它没有更改或此代码如何工作吗?

考虑一下,列表很大。我想知道如何在不建立索引的情况下更改变量的名称。

3 个答案:

答案 0 :(得分:4)

您的代码不起作用,因为当您执行names(li["first"]) = "sign"时,您正在执行的操作是:

  1. li["first"]-从列表中提取一个子列表。这将创建一个新列表。
  2. names(li["first"])-获取子列表的名称,而不是原始列表的名称。
  3. names(li["first"]) = "sign"-为子列表的一个成员分配新名称"sign"。原始列表li与此无关,在提取子列表的那一刻指令就丢失了它。在功能'names<-'退出时,子列表丢失,新子列表仅在功能'names<-'的环境中存在。

这绝对是一般性的,而不仅仅是列表。 如果要更改R对象的names属性,则必须首先获取该属性的值,并将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))

以上有效的代码(Ronak的代码)为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

就是这样。

答案 1 :(得分:0)

  

我想知道如何在不更改变量的情况下更改名称   索引。

您必须分配一个包含新名称的新向量。

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

结果是:

> names(l)
[1] "sign" "test"

答案 2 :(得分:0)

使用您的示例:

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

我们可以用[1]直接调用列表中的第一个元素,并用“ sign”(这是您所需要的)重命名。

names(li)[1] <- "sign"