我创建了一个虚构的数据框a
,使a = data.frame(b=1:10, c=sample(c("h","H","k","K"),10, replace = T))
a
b c
1 1 k
2 2 H
3 3 H
4 4 k
5 5 k
6 6 k
7 7 H
8 8 h
9 9 H
10 10 h
我想写一个简单的函数:
如果c等于k或K,则将b乘以1000,或者如果c等于h或H,则将b乘以100。
我发现transform
函数在搜索网站后对此有用,但我仍然想知道如何编写这样一个简单的函数。这就是我试图做的事情:
change_exp <- function(x){
if(x[2] %in% c("h","H")) {
x[1] <- x[1] * 100
} else if(x[2] %in% c("k","K")){
x[1] <- x[1] * 1000
}
}
我尝试运行它change_exp(a)
但无济于事。我的问题是如何编写这样的函数。
注意我发现以下将执行所需的操作:
transform( a,
b =
ifelse( c %in% c("h","H"), b*100,
ifelse( c %in% c("k","K"), b*1000, b)))
但是我也希望能够使用函数式编程。感谢
答案 0 :(得分:3)
使用某种查找表通常很方便,并且很容易推广到更大的样本而无需编写新代码:
key <- data.frame(mult=c(1000,100), val=c("k","h"))
key
# mult val
#1 1000 k
#2 100 h
key$mult[match(tolower(a$c),key$val)] * a$b
#[1] 100 200 3000 4000 500 6000 7000 8000 9000 1000
命名向量也以类似的方式工作,但从数据结构的角度来看可能不那么好:
key <- setNames(c(1000,100), c("k","h"))
a$b * key[tolower(a$c)]
# h h k k h k k k k h
# 100 200 3000 4000 500 6000 7000 8000 9000 1000
答案 1 :(得分:2)
我们可以在这里使用矢量化ifelse
a$b <- with(a, ifelse(tolower(c) == "k", b * 1000, b*100))
如果有k
和h
以外的值,我们可以使用嵌套的ifelse
with(a, ifelse(tolower(c) == "k", b * 1000, ifelse(tolower(c) == "h", b*100, b)))
我们可以对transform
transform(a, b = ifelse(tolower(c) == "k", b * 1000, b*100))
答案 2 :(得分:2)
另一种方法是使用which
:
change_exp <- function(x){
x[,1][which(x[,2] %in% c("h", "H"))] <- x[,1][which(x[,2] %in% c("h", "H"))] * 100
x[,1][which(x[,2] %in% c("k","K"))] <- x[,1][which(x[,2] %in% c("k","K"))] * 1000
return(x)
}
答案 3 :(得分:1)
我们可以使用data.table
library(data.table)
setDT(a)[, b1 := b*100][tolower(c) == "k", b1 := b * 1000]
如果我们需要转换多个值
key <- data.frame(c=c("k","K", "h", "H"), val = c(1000, 1000, 100, 100))
setDT(a)[key, b := b*val , on = "c"]
a
# b c
# 1: 1000 k
# 2: 200 H
# 3: 300 H
# 4: 4000 k
# 5: 5000 k
# 6: 6000 k
# 7: 700 H
# 8: 800 h
# 9: 900 H
#10: 1000 h
或另一个选项是dplyr
library(dplyr)
a %>%
mutate(b = if_else(tolower(c)=="k", b * 1000, b * 100))
# b c
#1 1000 k
#2 200 H
#3 300 H
#4 4000 k
#5 5000 k
#6 6000 k
#7 700 H
#8 800 h
#9 900 H
#10 1000 h