我正在尝试使用关联内存和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
非常感谢任何解释为什么会发生这种情况以及如何解决这个问题。感谢。
答案 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$pm
是factor
,而不是character
。您可以使用class(tdf$pm)
进行检查。这里发生的是"B"
实际上是2
的掩码(遵循打印输出中的顺序:Levels: + B h K m
),因此pd
的值为{ {1}}就2
而言,[
为100,因为您已经分配。
当您致电Multiplier[2]
(或data.frame
)时,您需要添加参数read.table
,或使用stringsAsFactors = FALSE
功能更改相应的全局选项。