R联想记忆不能按预期工作

时间:2014-09-14 23:42:03

标签: r memory

我正在尝试使用关联内存和ddply将列添加到数据框中。例如:

首先,我定义了关联和一个函数,它使用关联来计算一行中两个元素的产品(属性损坏和乘数)以获得美元的实际损害。这里," B"意思是Billion," m | M"是指MIllions等。

   validMultiplierLetter <- c("B", "h", "H", "k", "K", "m", "M")
    Multiplier <- c(1000000000, 100, 100, 1000, 1000, 1000000, 1000000)
    names(Multiplier) <- validMultiplierLetter

函数ploss(属性丢失)是:

ploss <- function(pd,pm) {
  if (pm %in% validMultiplierLetter) pd*Multiplier[pm]
  else 0
  }

这是一个示例数据框,其中包含列pd(属性损坏)和pm(乘数)以及用于创建pl(属性损失)列的ddply代码,这是属性损坏和乘数相关值的乘积。无效乘数等于0(例如,&#34; +&#34;)。

tdf <- data.frame(pd = c(5, 10, 15, 20, 25), pm = c("B", "m", "K", "+", "h"))

tldf <- ddply(tdf, .(pd, pm), transform, pl = ploss(pd,pm))

当我执行上面的代码时,我得到以下输出 - 你可以看到右边的乘数没有用于行。

> tldf
  pd pm    pl
1  5  B   500
2 10  m 10000
3 15  K 15000
4 20  +     0
5 25  h  2500

奇怪的是,当你传递常数时,乘数正常工作。但是,当您传递一个变量(其值与常量相同)时,由于某种原因您得到的结果不正确。

> Multiplier["B"]
    B 
1e+09 
> tdf$pm[1]
[1] B
Levels: + B h K m
> Multiplier[tdf$pm[1]]
  h 
100 

非常感谢任何解释为什么会发生这种情况以及如何解决这个问题。感谢。

2 个答案:

答案 0 :(得分:2)

问题在于tdf$pm是一个因素。当提出一个因子时,[将使用因子级别而不是字符值:

x <- 10:15
names(x) <- LETTERS[1:6]
x
##  A  B  C  D  E  F 
## 10 11 12 13 14 15 
x[c('A','F')]         # Lookup by name
##  A  F 
## 10 15 
x[factor(c('A','F'))] # Lookup by integer
##  A  B 
## 10 11

通过在因子周围使用as.character来解决此问题,以便将字符向量呈现给[

x[as.character(factor(c('A','F')))]
##  A  F 
## 10 15 

对于您的问题,您可以强制转换函数中的字符:

ddply(tdf, .(pd, pm), transform, pl = ploss(pd,as.character(pm)))
##   pd pm      pl
## 1  5  B 5.0e+09
## 2 10  m 1.0e+07
## 3 15  K 1.5e+04
## 4 20  + 0.0e+00
## 5 25  h 2.5e+03

此外,您可以以显而易见的方式对ploss函数进行矢量化,并直接使用transform完成工作:

ploss <- function(pd,pm) {
  ifelse(pm %in% validMultiplierLetter, pd*Multiplier[pm], 0)
}

transform(tdf, pl=ploss(pd, as.character(pm)))
##   pd pm      pl
## 1  5  B 5.0e+09
## 2 10  m 1.0e+07
## 3 15  K 1.5e+04
## 4 20  + 0.0e+00
## 5 25  h 2.5e+03

当然,as.character强制可以在ploss函数内,因此transform调用不需要:

ploss <- function(pd,pm) {
  ifelse(pm %in% validMultiplierLetter, pd*Multiplier[as.character(pm)], 0)
}

答案 1 :(得分:1)

我看到的问题是,如果您使用默认的R选项,tdf$pmfactor,而不是character。您可以使用class(tdf$pm)进行检查。这里发生的是"B"实际上是2的掩码(遵循打印输出中的顺序:Levels: + B h K m),因此pd的值为{ {1}}就2而言,[为100,因为您已经分配。

当您致电Multiplier[2](或data.frame)时,您需要添加参数read.table,或使用stringsAsFactors = FALSE功能更改相应的全局选项。