R语言 根据每一行的值改变一个新列

vfhzx4xs  于 2023-04-27  发布在  其他
关注(0)|答案(2)|浏览(150)

我有下面的玩具数据框。

toy.df <- data.frame(Name = c("group1", "group2", "group3", "group4", "group5", "group6", "group7"), 
                 col1 = c("pos", "neg", "NA", "pos","neg", "NA", "pos"),
                 col2 = c("pos", "pos", "NA", "pos","neg","NA", "neg"),
                 col3 = c("pos", "NA", "pos", "NA", "neg", "neg", "neg"))

我想变异一个新列,检查每行所有列的值。如果它们都是“pos”或“NA”,则变异“pos”,如果它们都是“neg”或“NA”,则变异“neg”,如果它们都是“pos”或“neg”或“NA”,则变异“both”。
新列如下所示:

col4 <- c("pos", "both", "pos", "pos","neg", "neg","both")

以下是最后一个 Dataframe :

Name  col1 col2 col3 col4
group1  pos  pos  pos  pos
group2  neg  pos  NA  both
group3  NA   NA   pos  pos
group4  pos  pos   NA  pos
group5  neg  neg  neg  neg
group6  NA   NA   neg  neg
group7  pos  neg  neg both
m1m5dgzv

m1m5dgzv1#

由于数据框中的“NA”是文字“NA”,我们需要将它转换为真实的的缺失值NA x x x na_if。然后使用case_when提供新列赋值的条件。我们需要rowwise才能在每行中工作。case_when中的最后一个TRUE ~ "unknown"捕获除了“pos”和“neg”之外的字符串在col1col3中。
我添加了两个条目来显示当所有行都是NA时,或者当列中有拼写错误时的行为。

library(dplyr)

toy.df %>% 
  rowwise() %>%  
  mutate(across(everything(), ~na_if(.x, "NA")),
         col4 = case_when(all(is.na(c_across(col1:col3))) ~ NA,
                          all(c_across(col1:col3) == "pos", na.rm = T) ~ "pos",
                          all(c_across(col1:col3) == "neg", na.rm = T) ~ "neg",
                          all(c_across(col1:col3) %in% c("pos", "neg", NA)) ~ "both",
                          TRUE ~ "unknown")) %>% 
  ungroup()

# A tibble: 9 × 5
  Name   col1  col2  col3  col4   
  <chr>  <chr> <chr> <chr> <chr>  
1 group1 pos   pos   pos   pos    
2 group2 neg   pos   NA    both   
3 group3 NA    NA    pos   pos    
4 group4 pos   pos   NA    pos    
5 group5 neg   neg   neg   neg    
6 group6 NA    NA    neg   neg    
7 group7 pos   neg   neg   both   
8 group8 NA    NA    NA    NA     
9 group9 pos   pos   typo  unknown

数据

toy.df <- structure(list(Name = c("group1", "group2", "group3", "group4", 
"group5", "group6", "group7", "group8", "group9"), col1 = c("pos", 
"neg", "NA", "pos", "neg", "NA", "pos", NA, "pos"), col2 = c("pos", 
"pos", "NA", "pos", "neg", "NA", "neg", NA, "pos"), col3 = c("pos", 
"NA", "pos", "NA", "neg", "neg", "neg", NA, "typo")), class = "data.frame", row.names = c(NA, 
-9L))
fzsnzjdm

fzsnzjdm2#

另一种方式:

toy.df$group6 <- apply(toy.df, 1, \(x) {
  val <- sort(unique(x[2:4]))
  if (val[1] == "NA") val = val[2:length(val)]
  if (length(val) == 2) {
    "both"
  } else if (val=="pos")
    "pos"
  else 
    "neg"
})
toy.df

输出:

Name col1 col2 col3 group6
1 group1  pos  pos  pos    pos
2 group2  neg  pos   NA   both
3 group3   NA   NA  pos    pos
4 group4  pos  pos   NA    pos
5 group5  neg  neg  neg    neg
6 group6   NA   NA  neg    neg
7 group7  pos  neg  neg   both

相关问题