R语言 如何将“ifelse”和“all”一起使用?

zvokhttg  于 2023-04-03  发布在  其他
关注(0)|答案(5)|浏览(179)

希望我不是重复别人的问题,也许是与我的另一个问题类似的问题。
我在努力
1.按ID对行进行分组
1.然后:a)将'A'分配给那些只收到产品'A'的人B)将'P'分配给那些只收到产品'P'的人c)将'A和P'分配给那些收到两种产品的人d)将NA分配给那些既没有收到A也没有收到P的人
我的数据df

df <- read.table(text =
"      ID Product
 1     1 A      
 2     1 A      
 3     1 A      
 4     2 NA     
 5     2 NA     
 6     3 P      
 7     3 P      
 8     4 A      
 9     4 P      
10     5 A      
11     6 P      
12     7 NA    ")

我想要的输出:

ID Product Group

 1     1 A       A    
 2     1 A       A    
 3     1 A       A    
 4     2 NA      NA   
 5     2 NA      NA   
 6     3 P       P    
 7     3 P       P    
 8     4 A       A_P  
 9     4 P       A_P  
10     5 A       A    
11     6 P       P    
12     7 NA      NA

我尝试了一些方法,但新的专栏没有出现:

df$Group <- df %>% 
  group_by(ID) %>%
  ifelse(all(df$Product==A), "A",
     ifelse(all(df$Product==P), "P",
            ifelse(all(df$Product==NA), "NA", "A_P") %>%
    ungroup()

我也试过:

df$group <- df%>% 
  group_by(ID) %>%
  if(all(df$Product=="A") {
    df$group="A"
  } else if(all(df$Product=="P") {
      df$group="P"
  } else if(all(df$Product==NA) {
        df$group=NA
        }  else {df$group="A_P"}

但是它一直说我的}不应该在那里,这对我来说没有意义?
我的另一个问题:可以在ifelse语句中使用all来表示非数值向量吗?
谢谢。

6tqwzwtp

6tqwzwtp1#

使用ave,避免使用if-else。

transform(df, Group=ave(Product, ID, FUN=\(x) {
  u <- paste(sort(unique(x)), collapse='_');replace(u, u == '', NA)}))
#    ID Product Group
# 1   1       A     A
# 2   1       A     A
# 3   1       A     A
# 4   2    <NA>  <NA>
# 5   2    <NA>  <NA>
# 6   3       P     P
# 7   3       P     P
# 8   4       A   A_P
# 9   4       P   A_P
# 10  5       A     A
# 11  6       P     P
# 12  7    <NA>  <NA>

可以考虑toString,使其以逗号分隔

transform(df, Group=ave(Product, ID, FUN=\(x) {
  u <- toString(sort(unique(x)));replace(u, u == '', NA)}))
#    ID Product Group
# 1   1       A     A
# 2   1       A     A
# 3   1       A     A
# 4   2    <NA>  <NA>
# 5   2    <NA>  <NA>
# 6   3       P     P
# 7   3       P     P
# 8   4       A  A, P
# 9   4       P  A, P
# 10  5       A     A
# 11  6       P     P
# 12  7    <NA>  <NA>
  • 数据:*
df <- structure(list(ID = c(1L, 1L, 1L, 2L, 2L, 3L, 3L, 4L, 4L, 5L, 
6L, 7L), Product = c("A", "A", "A", NA, NA, "P", "P", "A", "P", 
"A", "P", NA)), class = "data.frame", row.names = c("1", "2", 
"3", "4", "5", "6", "7", "8", "9", "10", "11", "12"))
wvyml7n5

wvyml7n52#

下面是我使用base R和几行可读代码的尝试。:)

xy <- read.table(text =
                   "      ID Product
 1     1 A      
 2     1 A      
 3     1 A      
 4     2 NA     
 5     2 NA     
 6     3 P      
 7     3 P      
 8     4 A      
 9     4 P      
10     5 A      
11     6 P      
12     7 NA    ")

xygroup <- split(x = xy, f = xy$ID)

xy.withgroup <- lapply(X = xygroup, FUN = function(x) {
  unique.products <- unique(x$Product)
  if (all(is.na(unique.products))) {
    group <- NA
  } else {
    group <- paste(unique.products, collapse = "_")
  }
  
  x$Group <- group
  x
})

do.call(rbind, xy.withgroup)

    ID Product Group
1.1  1       A     A
1.2  1       A     A
1.3  1       A     A
2.4  2    <NA>  <NA>
2.5  2    <NA>  <NA>
3.6  3       P     P
3.7  3       P     P
4.8  4       A   A_P
4.9  4       P   A_P
5    5       A     A
6    6       P     P
7    7    <NA>  <NA>
r8xiu3jd

r8xiu3jd3#

类似于@jay.sf:

df$Group <- tapply(df$Product, df$ID, \(x) { paste(sort(unique(x)), collapse = ' and ')})[df$ID]
df
#    ID Product   Group
# 1   1       A       A
# 2   1       A       A
# 3   1       A       A
# 4   2    <NA>      NA
# 5   2    <NA>      NA
# 6   3       P       P
# 7   3       P       P
# 8   4       A A and P
# 9   4       P A and P
# 10  5       A       A
# 11  6       P       P
# 12  7    <NA>      NA
w6lpcovy

w6lpcovy4#

我发现了一个非常丑陋的解决方案,使用pivot_wider然后paste0来创建一个新的data.table,其中包含您的组,然后使用right_join将组放回原始数据集中:

library(tidyverse)

df <- read.table(text =
                   "      ID Product
 1     1 A      
 2     1 A      
 3     1 A      
 4     2 NA     
 5     2 NA     
 6     3 P      
 7     3 P      
 8     4 A      
 9     4 P      
10     5 A      
11     6 P      
12     7 NA    ")

df = df %>% mutate(Product2=Product)

df %>% mutate(ID=as.factor(ID)) %>% 
distinct(ID, Product, .keep_all = T) %>% 
  pivot_wider(id_cols = ID, names_from = Product, values_from = Product2) %>%
  mutate(across(everything(),~ifelse(is.na(.x),"",.x))) %>%
  mutate(Group=paste0(A, P)) %>%
  select(ID, Group) %>%
  right_join(df ,by="ID") %>%
  mutate(Group=ifelse(Group=="",NA,Group))%>%
  select(-Product2)

有什么问题尽管问。

h9a6wy2h

h9a6wy2h5#

这里有一个方法。你的尝试所缺少的是你必须mutate数据集。
参见罗兰的评论。

df <- read.table(text =
                   "ID Product
 1     1 A      
 2     1 A      
 3     1 A      
 4     2 NA     
 5     2 NA     
 6     3 P      
 7     3 P      
 8     4 A      
 9     4 P      
10     5 A      
11     6 P      
12     7 NA", header = TRUE)

suppressPackageStartupMessages(
  library(dplyr)
)

df %>%
  group_by(ID) %>%
  mutate(Group = if(length(unique(Product)) == 1L) Product else paste(Product, collapse = "_"))
#> # A tibble: 12 × 3
#> # Groups:   ID [7]
#>       ID Product Group
#>    <int> <chr>   <chr>
#>  1     1 A       A    
#>  2     1 A       A    
#>  3     1 A       A    
#>  4     2 <NA>    <NA> 
#>  5     2 <NA>    <NA> 
#>  6     3 P       P    
#>  7     3 P       P    
#>  8     4 A       A_P  
#>  9     4 P       A_P  
#> 10     5 A       A    
#> 11     6 P       P    
#> 12     7 <NA>    <NA>

创建于2023-03-28带有reprex v2.0.2

相关问题