根据不同列中的多个值添加列

时间:2014-02-28 22:02:30

标签: r

我在数据框中有一堆od列,其中两列是这样的

col1 | col2
-----| -------------
 2   | M
 3   | B
 1   | m
 5   | K
 3   | k

我想要的是创建一个包含以下内容的新列:

如果col2中的值是k或K,则来自col1 * 10 ^ 3的值

           如果col2中的值为M或m,则为col1 * 10 ^ 6,
           col1 * 10 ^ 9如果col2中的值是B,
           如果是其他的话,则为0。

我知道在有二元条件时如何做ifelse,但我不知道如何用这样的多个条件来做。感谢。

4 个答案:

答案 0 :(得分:5)

您可以创建一个命名向量,并将其与“col2”列匹配以创建乘数。除M,m,K,k,B或b之外的所有值都会产生NA,因此如果您想要“0”,则只需从新列中对NA进行子集,然后将其替换为0手动。

Mults <- c(M = 10^6, m = 10^6, K = 10^3, k = 10^3, B = 10^9, b = 10^9)
Mults[mydf$col2]
#     M     B     m     K     k  <NA> 
# 1e+06 1e+09 1e+06 1e+03 1e+03    NA 
mydf$col3 <- mydf$col1 * Mults[mydf$col2]
mydf$col3[is.na(mydf$col3)] <- 0
mydf
#   col1 col2  col3
# 1    2    M 2e+06
# 2    3    B 3e+09
# 3    1    m 1e+06
# 4    5    K 5e+03
# 5    3    k 3e+03
# 6    3    x 0e+00

这是我使用的“mydf”(带有一个额外的行):

mydf <- structure(list(col1 = c(2, 3, 1, 5, 3, 3), col2 = c("M", "B", 
    "m", "K", "k", "x"), col3 = c(2e+06, 3e+09, 1e+06, 5000, 3000, 0)), 
    .Names = c("col1", "col2", "col3"), row.names = c(NA, 6L), 
    class = "data.frame")

答案 1 :(得分:4)

可以使用

switch

f <- function(multi, test)
  multi * switch(tolower(test),
         "m" = 10^6,
         "k" = 10^3,
         "b" = 10^9,
         0
  )
within(df, col3 <- mapply(f, col1, col2, SIMPLIFY=TRUE))
#   col1 col2  col3
# 1    2    M 2e+06
# 2    3    B 3e+09
# 3    1    m 1e+06
# 4    5    K 5e+03
# 5    3    k 3e+03

答案 2 :(得分:2)

这根本不优雅,但你可以这样做。问题是,如果你有更多可能的案例,它会变得很烦人。

DB <- data.frame(col1=c(2,3,1,5,3), col2=c("M","B","m","K","k"))
DB$col3 <- NA
DB$col3 <- ifelse(DB$col2=="K" | DB$col2=="k", DB$col1 * (10^3), DB$col3)
DB$col3 <- ifelse(DB$col2=="M" | DB$col2=="m", DB$col1 * (10^6), DB$col3)
DB$col3 <- ifelse(DB$col2=="B", DB$col1 * (10^9), DB$col3)
DB$col3 <- ifelse(is.na(DB$col2)==TRUE, 0, DB$col3)

或者您也可以这样做

DB <- data.frame(col1=c(2,3,1,5,3), col2=c("M","B","m","K","k"))
DB2 <- data.frame(col2=c("M","B","m","K","k"), tmp=c(10^6,10^9,10^6,10^3, 10^3))
DB<- merge(DB, DB2, by="col2")
DB$col3 <- DB$col1 * DB$tmp
DB$tmp <- NULL

答案 3 :(得分:1)

以下是使用mapplymget的另一种方式。

x <- with(mydf, list(K=col1*10^3, M=col1*10^6, B=col1*10^9, col2=toupper(col2)))
mydf$col3 <- 
do.call(mapply, c(function(K,M,B,col2) unlist(mget(col2, ifnotfound=0)), x))
#   col1 col2  col3
# 1    2    M 2e+06
# 2    3    B 3e+09
# 3    1    m 1e+06
# 4    5    K 5e+03
# 5    3    k 3e+03
# 6    3    x 0e+00