大小写匹配字符串

时间:2018-11-09 07:13:29

标签: r dplyr plyr matching case-when

我有一个df(下)和一个向量c(“ B”,“ F”),我想首先根据ID将df拆分为列表,然后如果“名称”列中的任何值匹配在向量c(“ B”,“ F”)中,然后在向量的所有行中为列“ Final”分配该特定值。

ID  Name
1   A   
1   B   
2   C   
1   D   
2   E   
2   F
3   C

我到目前为止尝试过的方法如下:

df_list <- dlply(df, "ID")
df_list_2 <- lapply(df_list, transform, 
                                  Final = case_when(
                                     sum(str_count(grepl(Name, "B"))) >= 1 ~ "B",
                                     sum(str_count(grepl(Name, "F"))) >= 1 ~ "F",
                                     TRUE ~ "No"))

我的最终结果应该如下

List 1 :

ID  Name    Final
1   A         B
1   B         B
1   D         B

List 2:



ID  Name    Final

2   C         F
2   E         F
2   F         F

List 3 :

 ID Name    Final
 3      C       NO

这只是一个示例数据,我必须在包含大约20个字符串值的向量列表的数百万条记录上运行

2 个答案:

答案 0 :(得分:2)

这是基于您的描述的基本R想法,

lapply(split(df, df$ID), function(i) {
       i1 <- i$Name[i$Name %in% v1]; 
       data.frame(i, Final = replace(i1, length(i1) == 0, 'NO'))
      })

给出,

$`1`
  ID Name Final
1  1    A     B
2  1    B     B
4  1    D     B

$`2`
  ID Name Final
3  2    C     F
5  2    E     F
6  2    F     F

$`3`
  ID Name Final
7  3    C    NO

数据:

dput(df)
structure(list(ID = c(1L, 1L, 2L, 1L, 2L, 2L, 3L), Name = c("A", 
"B", "C", "D", "E", "F", "C")), row.names = c(NA, -7L), class = "data.frame")

dput(v1)
c("B", "F")

编辑:如果最终元素多于1个,则可以转换为字符串,即

lapply(split(df, df$ID), function(i) {i1 <- i$Name[i$Name %in% v1]; 
                            data.frame(i, Final = ifelse(length(unique(i1)) > 1, 
                             toString(unique(i1)), ifelse(length(unique(i1)) == 0, 'NO', i1)))})

答案 1 :(得分:1)

您还可以使用group_by中的dplyr

library(plyr)  # Load plyr first if you use it with dplyr
library(dplyr)

match_vector <- c("B", "F")

df_new <- df %>% 
  group_by(ID) %>% 
  mutate(Final = if_else(any(Name %in% match_vector), 
                         paste(match_vector[match_vector %in% Name], collapse = ";"), 
                         "No"))

df_new
# A tibble: 7 x 3
# Groups:   ID [3]
#     ID Name  Final
#   <int> <chr> <chr>
# 1     1 A     B    
# 2     1 B     B    
# 3     2 C     F    
# 4     1 D     B    
# 5     2 E     F    
# 6     2 F     F    
# 7     3 C     No   

我在这里使用paste(match_vector[match_vector %in% Name], collapse = ";"),如果有多个匹配项,它将在“最终”列中打印所有匹配项。如果您不希望这样做,请使用match_vector[match_vector %in% Name][1]获得第一场比赛。

如果您需要列表结构,则可以使用split(基于R)或dlplyplyr):

dlply(df_new, "ID")
split(df_new, df_new$ID)

$`1`
# A tibble: 3 x 3
# Groups:   ID [1]
     ID Name  Final
  <int> <chr> <chr>
1     1 A     B    
2     1 B     B    
3     1 D     B    

$`2`
# A tibble: 3 x 3
# Groups:   ID [1]
     ID Name  Final
  <int> <chr> <chr>
1     2 C     F    
2     2 E     F    
3     2 F     F    

$`3`
# A tibble: 1 x 3
# Groups:   ID [1]
     ID Name  Final
  <int> <chr> <chr>
1     3 C     No