r编写一个函数,根据第二列转换一列

时间:2017-01-17 03:40:24

标签: r

我创建了一个虚构的数据框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)))

但是我也希望能够使用函数式编程。感谢

4 个答案:

答案 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))

如果有kh以外的值,我们可以使用嵌套的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