【问题标题】:Creating a new variable创建一个新变量
【发布时间】:2014-10-01 13:03:23
【问题描述】:

嗨,我有一个看起来像这样的数据集

bankname    bankid  year    totass  invloc1 invamt1 invloc2 invamt2 invloc3 invamt3   
Bank A  1   1881    244789  Philadelphia    7250.32 New York    20218.20    Philadelphia    29513.4   
Bank B  2   1881    195755  Pittsburgh  10243.60    NA  1851.51 NA  NA   
Bank C  3   1881    107736  New York    13357.80    Wilkes-Barre    17761.20    NA  NA   
Bank D  4   1881    170600  Philadelphia    3.35    Philadelphia    2.00    NA  NA   
Bank E  5   1881    32000000    New York    351266.00   New York    314012.00       NA   

但我想为每个银行使用 invloc 和 invamt 变量创建一个名为 NY_tot 的新变量。对于每家银行,如果他们的 invloc 是纽约,那么总和 invamt。 invloc1 和 invamt1 一起去。因此,我希望这个数据集看起来像这样。

bankname    bankid  year    totass  invloc1 invamt1 invloc2 invamt2 invloc3 invamt3 NY_tot   
Bank A  1   1881    244789  Philadelphia    7250.32 New York    20218.20    Philadelphia    29513.4 20218.20   
Bank B  2   1881    195755  Pittsburgh  10243.60    NA  1851.51 NA  NA  0   
Bank C  3   1881    107736  New York    13357.80    Wilkes-Barre    17761.20    NA  NA  13357.80   
Bank D  4   1881    170600  Philadelphia    3.35    Philadelphia    2.00    NA  NA  0   
Bank E  5   1881    32000000    New York    351266.00   New York    314012.00       NA  665278   

这是我正在使用的数据集

bankname <- c("Bank A","Bank B","Bank C","Bank D","Bank E")
bankid <- c( 1, 2,  3,  4,  5)
year<- c( 1881, 1881,   1881,   1881,   1881)
totass  <- c(244789,    195755, 107736, 170600, 32000000)
invloc1 <-c("Philadelphia","Pittsburgh","New York","Philadelphia","New York")
invamt1<-c(7250.32,10243.6,13357.8,3.35,351266)
invloc2<-c("New York","NA","Wilkes-Barre","Philadelphia","New York")
invamt2<-c(20218.2,1851.51,17761.2,2,314012)
invloc3<-c("Philadelphia","NA","NA","NA","")
invamt3<-c(29513.4,NA,NA,NA,NA)
bankdata<-data.frame(bankname, bankid,year,totass, invloc1, invamt1, invloc2, invamt2, invloc3, invamt3)

当我尝试以下代码时:

将因子变量(invloc)更改为字符

i <- sapply(bankdata, is.factor)
bankdata[i] <- lapply(bankdata[i], as.character)  

然后新建一个变量

for(i in 1:nrow(bankdata)){
 bankdata$NY_tot<-0
for(j in 1:3){
if((!is.na(bankdata[i,paste("invloc",j,sep="")])) && (bankdata[i,paste("invloc",j,sep="")]=="New York")){
  if (!is.na(bankdata[i,paste("invamt",j,sep="")])){
    bankdata$NY_tot[i]<-bankdata$NY_tot[i]+bankdata[i,paste("invamt",j,sep="")]
      }
    }
  }
}

我在NY_tot 变量中得到 0。你能告诉我为什么吗?

提前谢谢你!

【问题讨论】:

  • 因为您为每一行重新定义了bankdata$NY_tot&lt;-0。您可能希望在循环之外执行此操作。
  • 您正在使用 for 循环,您应该使用矢量化。这会导致代码变慢。
  • 我怎样才能更有效地做到这一点?你能给我示例代码吗?谢谢大家。
  • 这可能可以用 ifelse 解决,但是,您的数据框缺少 invamt 列,我无法真正弄清楚您想要什么,所以我无法用您上面的信息提供答案.
  • 我认为出于安全考虑,您应该使用lapply(bankdata[i], function(x) as.character(x))而不是lapply(bankdata[i], as.character)

标签: r rstudio


【解决方案1】:

正如其他人在 cmets 中所说的那样,您不需要弄乱 for 循环来执行此操作。 R 有大量精美的内置函数可以快速处理此类问题。

在这种情况下,您的解决方案是ifelse。对于您要使用哪些列,我有些困惑,但请尝试以下操作:

bankdata$NY_tot=ifelse(bankdata$invloc1=="New York",sum(bankdata$invamt1,bankdata$invamt2),NA)

这里发生了什么? ifelse 是这样工作的:

ifelse(conition, value_if_true, value_if_false)

因此,在您的情况下,该函数检查invloc1 的值是否为"New York",如果是则返回总和,否则返回NA。最好的部分是它会自动逐行执行此操作,因此您无需手动迭代数据帧,这就是导致上述代码出现问题的原因。

编辑:正如下面@Richard Scriven 所建议的,您可以避免使用withwithin 输入数据框的名称四次,例如:

bankdata<-within(bankdata, NY_tot=ifelse(invloc1=="New York"),sum(invamt1,invamt2),NA)

这是一个我将在余生中使用的绝妙技巧,它基本上告诉 R 给定的所有变量名都与 bankdata 相关联,因此您不必一直输入它。

【讨论】:

  • @Richard Scriven,我已经用 R 编码一年多了,但从未发现过with/within...我认为你改变了我的生活。
  • 而且您也处于不同的环境中。 a &lt;- "H"; x &lt;- list(a = 1, b = 2); with(x, list(ls(), mget(ls()), get("a", .GlobalEnv)))。很整洁的东西
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多