使用for循环创建新列

时间:2017-07-09 12:20:51

标签: r

我是R的新手(有Stata背景的经济学家),我无法让嵌套for循环为我工作。我知道问题是我对如何使用循环计数器作为变量名的一部分没有很好的理解。

一点背景知识。我有数据框,其中包含不同规模住宅(1间卧室,2间卧室等)的平均租金数据以及年度收入(平均值,中位数和各种百分位数)的数据。我正在尝试生成一系列新列,其中包含这两项内容的比例(租金率/平均收入)。

具体来说,我的变量是:

  • beds1, beds2, beds3, beds4

  • mean, median, p10, p25, p75, p90

所以你看我需要生成24列新的成本/收益数据。我可以写出24行代码,但我不想这样做。更重要的是,我想在R中学习一种有效的方法。在Stata中我可以非常简单地使用嵌套的for循环,但我无法在R中使用它。这是我的代码到目前为止。< / p>

for (i in 1:4) {
    stat <- c("median", "mean", "p10", "p25", "p75","p90")
    for (x in stat) {
        df$beds[i]_[x] <- round((df$beds[i]/df$[x]),digits=3)
    }
}

当我运行此代码时,我得到的错误是

Error: unexpected input in:
"    for (x in stat) {
    df$beds[i]_"
>     }
Error: unexpected '}' in "    }"
> }
Error: unexpected '}' in "}"

我尝试使用双括号[[]],但这并没有改变结果。如果有人对动态变量名称不起作用的原因有所了解,请告诉我。更好的是,因为我猜R中的循环是邪恶的,如果有人知道使用lapply来完成这项工作的方法,我也很乐意听到。

修改

感谢@Spacedman的评论。我想我得到了你所说的话。那么这是否意味着我无论如何都不想在R中做我想做的事情?

var1 <- c("beds1", "beds2")
var2 <- c("mean", "median")

for (i in 1:2) {
    for (j in 1:2) {
        df$var1[i]_var2[j] <- df$var1[i]/df$var2[j]
    }
}

我认为这应该抓住列表var1var2的元素,这样当i=1j=1时,df$var1[i]/df$var2[j]应该是df$beds1/df$mean }。或者R会生气,并认为我试图划分字符串?

来自@SPACEEMAN的答案的最终编辑

谢谢@Spacedman。我喜欢你的剧透,谢谢你提供额外的帮助。我没有完全理解你在上一篇文章后引用列的两种方式之间的区别,但我认为我现在有了更好的想法。我做了一些调整,现在我有一些完美的东西。再次感谢!

beds <- c("beds1", "beds2", "beds3", "beds4")
stat <- c("median", "mean", "p10", "p25", "p75","p90")

for(i in beds){
    for(x in stat){
        res = paste0(i,"_",x)
        df[[res]]=round(df[[i]]/df[[x]],digits=3)
    }
}

1 个答案:

答案 0 :(得分:2)

R不是像您可能习惯的其他语言一样的宏扩展语言。

x[i],如果i=123,则“展开”为x123。它获取向量的第123个元素x的值。

所以df$beds[i]尝试获取向量df$beds的第i个元素。

你需要知道两件事:

  1. 如何从其他字符串构造字符串。
  2. 为此,您可以使用paste0

    > for(i in 1:4){
    +  print(paste0("beds",i))
    + }
    [1] "beds1"
    [1] "beds2"
    [1] "beds3"
    [1] "beds4"
    
    1. 如何按名称访问列。
    2. 为此,您可以使用双方括号。在列表中:

      > z = list()
      > n = "thing"
      

      Double squabs评估他们的指数并使用它。所以:

      > z[[n]] = 99
      

      将设置z$thing,但美元符号索引是文字的,所以:

      > z$n = 123
      

      将设置z$n

      > z
      $thing
      [1] 99
      
      $n
      [1] 123
      

      希望这有足够的提示让你通过。它应该全部包含在网上的基础R教程中。

      扰流

      如果你想弄清楚如何自己动手,现在就把目光移开......

      首先,让我们创建一个示例数据框 - 您应该在问题中包含这样的内容,以便我们可以使用常见的测试数据。我只有三张床和两张统计数据:

      > df = data.frame(
           beds1=c(1,2,3),
           beds2=c(5,2,3),
           beds3=c(6,6,6),
           mean=c(8,4,3),
           median=c(1,7,4))
      > df
            beds1 beds2 beds3 mean median
          1     1     5     6    8      1
          2     2     2     6    4      7
          3     3     3     6    3      4
      

      现在的工作。我们遍历床号和角色统计数据。通过将“床位”粘贴到数字bed,床栏名称存储在i中。我们通过将res粘贴到"beds"i以及"_"中的统计名称来计算给定床号和统计数据的结果列(x)的名称1}}。

      然后通过将床数除以stat来将新的结果列设置为该值。我们使用[[z]]按名称获取列:

      > for(i in 1:3){
        stats=c("mean","median")
        for(x in stats){
          bed = paste0("beds",i)
          res = paste0("beds",i,"_",x)
          df[[res]]=round(df[[bed]]/df[[x]],digits=3)
        }
       }
      

      导致......

      > df
        beds1 beds2 beds3 mean median beds1_mean beds1_median beds2_mean beds2_median
      1     1     5     6    8      1      0.125        1.000      0.625        5.000
      2     2     2     6    4      7      0.500        0.286      0.500        0.286
      3     3     3     6    3      4      1.000        0.750      1.000        0.750
        beds3_mean beds3_median
      1       0.75        6.000
      2       1.50        0.857
      3       2.00        1.500
      >