【问题标题】:How to name a column using cbind, in a loop如何在循环中使用 cbind 命名列
【发布时间】:2019-11-24 15:54:51
【问题描述】:

我正在使用循环来使用 cbind 重命名列。每次我尝试使用循环索引 (i) 命名列时,它不使用索引,而是将 i 放入列名。我希望它显示原始名称中的实际名称

x <- seq(0, 50, by = 1)
y <- seq(50, 100, by = 1)
z <- seq(25, 75, by = 1)

df <- data.frame(cbind(x, y, z))

df_final <- NULL
for (i in colnames(df)){

#PROBLEM: Column names becomes i instead of the actual column names
df_final <- cbind(df_final, i = df[,i])

}
df_final

【问题讨论】:

  • data.frame(cbind(x, y, z)) 之后的列名已经是 x y z。你想在循环中做什么?
  • 旁注:尽量避免用data.frame(cbind(...))创建数据框;充其量是多余的,最坏的情况是会导致意外/不正确的结果。 data.frame(x = x,y = y,z = z) 就足够了。
  • 对于您的问题,cbind 是重命名列名的错误工具。您可以使用df_final[["new_col"]] &lt;- foo 创建一个新列,并使用存储在df_final[[bar]] &lt;- foo 变量中的名称来执行此操作,其中bar &lt;- "new_var"
  • @joran,您知道迭代 cbinding 是否与迭代 rbinding 具有相同的后果(内存方面)?也就是说,cbind 操作是每次都完全复制帧,还是只是有效地扩展list
  • @r2evans 我猜cbind 在数据帧上调用时实际上只是data.frame(...) 的包装器,它已经变得相当高效。当我用tracemem 尝试一个小例子时,我没有看到任何复制的证据。

标签: r loops rename cbind columnname


【解决方案1】:

一个简单的解决方案是在循环中设置 colname,如:

df_final <- NULL
for (i in colnames(df)){
  df_final <- cbind(df_final, df[,i])
  colnames(df_final)[ncol(df_final)]  <- i
}
colnames(df_final)
#[1] "x" "y" "z"
str(df_final)
# num [1:51, 1:3] 0 1 2 3 4 5 6 7 8 9 ...
# - attr(*, "dimnames")=List of 2
#  ..$ : NULL
#  ..$ : chr [1:3] "x" "y" "z"

对于使用x[[i]] &lt;- value的方法,x需要有行:

df_final <- data.frame()[seq_len(nrow(df)),0] #Create empty data frame with rows
for (i in colnames(df)){
  df_final[[i]] <- df[,i]
}
colnames(df_final)
#[1] "x" "y" "z"
str(df_final)
#'data.frame':   51 obs. of  3 variables:
# $ x: num  0 1 2 3 4 5 6 7 8 9 ...
# $ y: num  50 51 52 53 54 55 56 57 58 59 ...
# $ z: num  25 26 27 28 29 30 31 32 33 34 ...

否则它将创建一个列表:

df_final <- NULL
for (i in colnames(df)){
  df_final[[i]] <- df[,i]
}
colnames(df_final)
#NULL
str(df_final)
#List of 3
# $ x: num [1:51] 0 1 2 3 4 5 6 7 8 9 ...
# $ y: num [1:51] 50 51 52 53 54 55 56 57 58 59 ...
# $ z: num [1:51] 25 26 27 28 29 30 31 32 33 34 ...

df_final  <- do.call("cbind", df_final)
colnames(df_final)
#[1] "x" "y" "z"
str(df_final)
# num [1:51, 1:3] 0 1 2 3 4 5 6 7 8 9 ...
# - attr(*, "dimnames")=List of 2
#  ..$ : NULL
#  ..$ : chr [1:3] "x" "y" "z"

当使用 sapply 而不是 for 完成循环时,解决方案是:

df_final <- sapply(colnames(df), function(i) {df[,i]})
colnames(df_final)
#[1] "x" "y" "z"
str(df_final)
# num [1:51, 1:3] 0 1 2 3 4 5 6 7 8 9 ...
# - attr(*, "dimnames")=List of 2
#  ..$ : NULL
#  ..$ : chr [1:3] "x" "y" "z"

或者只是子集:

df_final <- df[colnames(df)]
colnames(df_final)
#[1] "x" "y" "z"
str(df_final)
#'data.frame':   51 obs. of  3 variables:
# $ x: num  0 1 2 3 4 5 6 7 8 9 ...
# $ y: num  50 51 52 53 54 55 56 57 58 59 ...
# $ z: num  25 26 27 28 29 30 31 32 33 34 ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 2012-04-14
    • 1970-01-01
    • 1970-01-01
    • 2020-06-21
    • 2012-06-21
    相关资源
    最近更新 更多