如果不是NA,则将一列粘贴到所有其他列

时间:2018-08-16 11:46:46

标签: r dataframe

我的问题是我有一个5列的数据框,其中4列包含名称,而1列包含状态。例如

   X1       X2      X3       X4       X5
1 name1     NA     name3     NA     active   
2 name1   name2     NA      name4   inactive
3 NA      name2    name3    name4   unknown
4 name1   name2     NA       NA     inactive
5 name1   name2    name3    name4   unknown

我想做的是在每个X1,X2,X3和X4之间交替使用col X5,并用下划线(name1_activename2_inactive)将它们粘贴在一起考虑到NA的情况。

   X1      X5       X2      X5        X3      X5       X4       X5
1 name1  active     NA      NA      name3   active     NA       NA   
2 name1  inactive  name2  inactive   NA       NA      name4   inactive
3 NA       NA      name2  unknown   name3   unknown   name4   unknown
4 name1  inactive  name2  inactive   NA       NA       NA       NA
5 name1  unknown   name2  unknown   name3   unknown   name4   unknown

输出:

       X1             X2                X3             X4 
1 name1_active        NA           name3_active        NA     
2 name1_inactive  name2_inactive        NA         name4_inactive
3     NA          name2_unknown    name3_unknown   name4_unknown
4 name1_inactive  name2_inactive        NA             NA   
5 name1_unknown   name2_unknown    name3_unknown   name4_unknown

6 个答案:

答案 0 :(得分:8)

尝试:

toaster.pop

答案 1 :(得分:4)

这类似于r.user.05apr的答案,但我想表明我们可以使用lapply直接循环并替换原始数据框中的列。

dat[, paste0("X", 1:4)] <- lapply(dat[, paste0("X", 1:4)], function(x){
  ifelse(!is.na(x), paste(x, dat$X5, sep = "_"), x)
})

dat$X5 <- NULL

dat
#               X1             X2            X3             X4
# 1   name1_active           <NA>  name3_active           <NA>
# 2 name1_inactive name2_inactive          <NA> name4_inactive
# 3           <NA>  name2_unknown name3_unknown  name4_unknown
# 4 name1_inactive name2_inactive          <NA>           <NA>
# 5  name1_unknown  name2_unknown name3_unknown  name4_unknown

我们还可以使用mutate_at软件包中的dplyr

library(dplyr)

dat2 <- dat %>%
  mutate_at(vars(-X5), funs(ifelse(!is.na(.), paste(., X5, sep = "_"), .))) %>%
  select(-X5)
dat2
#               X1             X2            X3             X4
# 1   name1_active           <NA>  name3_active           <NA>
# 2 name1_inactive name2_inactive          <NA> name4_inactive
# 3           <NA>  name2_unknown name3_unknown  name4_unknown
# 4 name1_inactive name2_inactive          <NA>           <NA>
# 5  name1_unknown  name2_unknown name3_unknown  name4_unknown

数据

dat <- read.table(text = "   X1       X2      X3       X4       X5
1 name1     NA     name3     NA     active   
                  2 name1   name2     NA      name4   inactive
                  3 NA      name2    name3    name4   unknown
                  4 name1   name2     NA       NA     inactive
                  5 name1   name2    name3    name4   unknown",
                  header = TRUE, stringsAsFactors = FALSE)

答案 2 :(得分:3)

我将purrr + stringr解决方案放入锅中;)

library(purrr)
library(stringr)

map_df(my_data[, 1:4], ~ str_c(.x, "_", my_data$X5))

# A tibble: 5 x 4
#   X1             X2             X3            X4            
#   <chr>          <chr>          <chr>         <chr>         
# 1 name1_active   NA             name3_active  NA            
# 2 name1_inactive name2_inactive NA            name4_inactive
# 3 NA             name2_unknown  name3_unknown name4_unknown 
# 4 name1_inactive name2_inactive NA            NA            
# 5 name1_unknown  name2_unknown  name3_unknown name4_unknown 

map_df自动返回一个tibble,而str_c的缺失值是“传染性的”。

答案 3 :(得分:1)

我使用apply的解决方案:

df <- data.frame(A = c('a1', 'a2', 'a3'))
df$B <- c('b1', 'b2', 'b3')
df$C <- c('c1', 'c2', 'c3')
df$STATUS <- c('OK', 'BAD', 'OK')

df1 <- apply(df[,1:(ncol(df)-1)], 2, function(X) {
  X <- paste0(X, "_", df$STATUS)
})
df1

结果:

     A        B        C       
[1,] "a1_OK"  "b1_OK"  "c1_OK" 
[2,] "a2_BAD" "b2_BAD" "c2_BAD"
[3,] "a3_OK"  "b3_OK"  "c3_OK" 

答案 4 :(得分:0)

使用dplyr,如果我以一种蛮力的方式正确理解: (我假设您想使用NA_something和something_NA而不是NA_NA保留案例)

df2 <- df %>%
    mutate(X1 = paste(X1,X5,sep="_")) %>%
    mutate(X1 = ifelse(X1 %in% c("NA_NA"),NA,X1)) %>%
    mutate(X2 = paste(X2,X5,sep="_")) %>%
    mutate(X2 = ifelse(X2 %in% c("NA_NA"),NA,X2)) %>%
    mutate(X3 = paste(X3,X5,sep="_")) %>%
    mutate(X3 = ifelse(X3 %in% c("NA_NA"),NA,X3) %>%
    mutate(X4 = paste(X4,X5,sep="_")) %>%
    mutate(X4 = ifelse(X4 %in% c("NA_NA"),NA,X4)) %>%
    select(-X5)

答案 5 :(得分:0)

如果您分配给lapply而不是d[],则可以直接使用d

d[] <- lapply(d, function(x) ifelse(is.na(x), NA, paste(x,d$X5, sep="_")))
# or, excluding the 5th col
d[,-5] <- lapply(d[,-5], function(x) ifelse(is.na(x), NA, paste(x,d$X5, sep="_")))

或者,如果您不想覆盖d中的值,则可以使用外观精美的"[<-"方法:

"[<-"(d,,-5, lapply(d[,-5], function(.) ifelse(is.na(.), NA, paste(., d$X5, sep="_"))))
# notice two commas with nothing in between - not a typo

最后,一个environment()友好的解决方案:

within(d, 
       list2env(
        lapply(d, 
               function(x) ifelse(is.na(x), NA, paste(x,X5, sep="_"))), 
        environment()))