更改数据框列中的值,具体取决于每个可能值的数量

时间:2015-05-05 12:47:13

标签: r dataframe

我的数据框看起来像这样:

UIView

我想编写一个能够查看每个' b'列并询问它是否包含值' HP'。如果是,那么其他六个' b'列包含' CP'或者' KP',我想改变价值' HP'进入' CP'或者' KP'取决于哪个是多数。如果CP占多数,请将HP更改为CP。如果KP占多数,则将HP更改为KP。

(请注意,b1和b2,b3和b4等的值总是相同的,所以实际上只需要查看4列,b1,b3,b5和b7)。

澄清一下,如果列是例如HP HP CP CP CP CP KP KP,我想将两个HP更改为CP(并使其他列保持不变)。

所以,我给出的例子将成为:

chr <- c(1,1,1,1,1)
b1 <- c('HP', 'HP', 'CP', 'CP', 'KP')
b2 <- c('HP', 'HP', 'CP', 'CP', 'KP')
b3 <- c('CP', 'KP', 'CP', 'HP', 'CP')
b4 <- c('CP', 'KP', 'CP', 'HP', 'CP')
b5 <- c('CP', 'CP', 'KP', 'KP', 'HP')
b6 <- c('CP', 'CP', 'KP', 'KP', 'HP')
b7 <- c('CP', 'KP', 'HP', 'CP', 'CP')
b8 <- c('CP', 'KP', 'HP', 'CP', 'CP')
df <- data.frame(chr, b1,b2,b3,b4,b5,b6,b7,b8)

我用if语句编写了一个函数(仅用于df $ b1),但它不起作用。 (请注意HP更改为KP或CP的规则取决于有多少其他CP或KP):

 chr <- c(1,1,1,1,1)
    b1 <- c('CP', 'KP', 'CP', 'CP', 'KP')
    b2 <- c('CP', 'KP', 'CP', 'CP', 'KP')
    b3 <- c('CP', 'KP', 'CP', 'CP', 'CP')
    b4 <- c('CP', 'KP', 'CP', 'CP', 'CP')
    b5 <- c('CP', 'CP', 'KP', 'KP', 'CP')
    b6 <- c('CP', 'CP', 'KP', 'KP', 'CP')
    b7 <- c('CP', 'KP', 'CP', 'CP', 'CP')
    b8 <- c('CP', 'KP', 'CP', 'CP', 'CP')
    df <- data.frame(chr, b1,b2,b3,b4,b5,b6,b7,b8)
    df

非常感谢您的帮助。我真的坚持这个。

编辑:这是我的实际数据样本,它比我上面给出的例子更复杂。

fun <- function(df){

if(df$b1 == 'HP' && df$b3 == 'CP' && df$b5 == 'CP' && df$b7 == 'CP') {df$b1 <- 'KP'} 
if(df$b1 == 'HP' && df$b3 == 'KP' && df$b5 == 'CP' && df$b7 == 'CP') {df$b1 <- 'CP'}
if(df$b1 == 'HP' && df$b3 == 'CP' && df$b5 == 'KP' && df$b7 == 'CP') {df$b1 <- 'CP'}
if(df$b1 == 'HP' && df$b3 == 'CP' && df$b5 == 'CP' && df$b7 == 'KP') {df$b1 <- 'CP'}
if(df$b1 == 'HP' && df$b3 == 'KP' && df$b5 == 'KP' && df$b7 == 'CP') {df$b1 <- 'KP'} 
if(df$b1 == 'HP' && df$b3 == 'KP' && df$b5 == 'CP' && df$b7 == 'KP') {df$b1 <- 'KP'} 
if(df$b1 == 'HP' && df$b3 == 'CP' && df$b5 == 'KP' && df$b7 == 'KP') {df$b1 <- 'KP'} 
if(df$b1 == 'HP' && df$b3 == 'KP' && df$b5 == 'KP' && df$b7 == 'KP') {df$b1 <- 'CP'}

df$b2 <-df$b1

}

1 个答案:

答案 0 :(得分:3)

您可以尝试:

t(apply(df[,-1], 1, function(rg){
                occ_rg <- table(rg)
                rg[grep("HP",rg)] <- names(occ_rg)[which.max(occ_rg)]
                return(rg)}))

所以,拥有你的新df:

df <- data.frame(chr=df[, 1], t(apply(df[,-1], 1, function(rg){
                                                  occ_rg <- table(rg)
                                                  rg[grep("HP",rg)] <- names(occ_rg)[which.max(occ_rg)]
                                                  return(rg)})), 
                 stringsAsFactors=F)
#  chr b1 b2 b3 b4 b5 b6 b7 b8
#1   1 CP CP CP CP CP CP CP CP
#2   1 KP KP KP KP CP CP KP KP
#3   1 CP CP CP CP KP KP CP CP
#4   1 CP CP CP CP KP KP CP CP
#5   1 KP KP CP CP CP CP CP CP

编辑

如果您有其他列,而您想要更改的列是唯一以“b”开头的列,您可以执行以下操作:

df[, grepl("^b", colnames(df))] <- t(apply(df[, grepl("^b", colnames(df))], 
                                           1, 
                                           function(rg){
                                                   occ_rg <- table(rg)
                                                   rg[grep("HP",rg)] <- names(occ_rg)[which.max(occ_rg)]
                                                   return(rg)}))

<强> 实施例

有了这个df:

#  chr c1 b1 b2 b3 b4 b5 b6 b7 b8 c2
#1   1  1 HP HP CP CP CP CP CP CP 11
#2   1  2 HP HP KP KP CP CP KP KP 12
#3   1  3 CP CP CP CP KP KP HP HP 13
#4   1  4 CP CP HP HP KP KP CP CP 14
#5   1  5 KP KP CP CP HP HP CP CP 15

你得到:

#  chr c1 b1 b2 b3 b4 b5 b6 b7 b8 c2
#1   1  1 CP CP CP CP CP CP CP CP 11
#2   1  2 KP KP KP KP CP CP KP KP 12
#3   1  3 CP CP CP CP KP KP CP CP 13
#4   1  4 CP CP CP CP KP KP CP CP 14
#5   1  5 KP KP CP CP CP CP CP CP 15

编辑2

如果您有其他值而不是“HP”,“CP”和“KP”,并希望用“CP”或“KP”替换“HP”,具体取决于发生的最多,您可以这样做:

df[, grepl("^b", colnames(df))] <- t(apply(df[, grepl("^b", colnames(df))], 
                                           1, 
                                           function(rg){
                                                   occ_rg <- table(rg)
                                                   occ_rg <- occ_rg[grepl("KP|CP", names(occ_rg))]
                                                   rg[grep("HP",rg)] <- names(occ_rg)[which.max(occ_rg)]
                                                   return(rg)}))

说明(对于edit2):

df[, grepl("^b", colnames(df))] <- # only the columns beginning with b are considered (so the other ones will remain untouched)

      t( # the results of apply will be transposed
         apply(df[, grepl("^b", colnames(df))], # apply on df with only the columns beginning by b
               1, # by row
               function(rg){ # a function that takes a vector "rg" as input
                   occ_rg <- table(rg) # computes the table
                   occ_rg <- occ_rg[grepl("KP|CP", names(occ_rg))] # keep only the occurrences of either "KP" or "CP"
                   rg[grep("HP",rg)] <- names(occ_rg)[which.max(occ_rg)] # replace in the vector rg the "HP" elements by "KP" or "CP" depending on which occurs the most
                   return(rg) # finally returns the vector rg
               }))