2014-02-28 40 views
0

我有一个数据帧一堆OD列,其中两个是这样添加基于多个值的列

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

我要的是创建一个新的列将包含:从COL1

值* 10^3如果在COL2值是K或K,
COL1 * 10^6,如果在COL2的值是M或m,
COL1 * 10^9如果在COL2的值是B,
和0,如果它是别的。

我知道如何做ifelse当有二进制条件,但我不知道如何做到这一点与多个条件。谢谢。

回答

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") 
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 
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 
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