提取超过2列dataframe R中的行式公共子字符串

dgtucam1  于 2023-02-14  发布在  其他
关注(0)|答案(3)|浏览(179)

在微生物学谱系分类器中,我想比较三种方法:我有科、属和种的分类等级,每个等级之间用“”分隔;“在R Dataframe (df)中。
作为一个玩具例子,我有下一个df:

df <- data.frame(classifier_a = c("Lachnospiraceae;Blautia;NA", 'Succinivibrionaceae;Succinivibrio;NA', 'NA;NA;NA'), 
                 classifier_b = c('Lachnospiraceae;Blautia;Blautia faecis', 'Succinivibrionaceae;Succinivibrio;NA', 'UGC-10;NA;NA'), 
                 classifier_c= c('Lachnospiraceae;Blautia;Blautia faecis', 'Succinivibrionaceae;Succinivibrio;Succinivibrio dextrinosolvens', 'NA;NA;NA'))

df

对于每一行,我都有兴趣找出给出相同结果的方法(为此,我使用统计模式概念)。然而,如果我应用此方法,则不会按我的期望工作,因为我得到以下输出:

df$Row_mode <- apply(df[,1:3],1, function(x) {names(which.max(table(factor(x,unique(x)))))})

df <- data.frame(classifier_a = c("Lachnospiraceae;Blautia;NA", 'Succinivibrionaceae;Succinivibrio;NA', 'NA;NA;NA'), 
                 classifier_b = c('Lachnospiraceae;Blautia;Blautia faecis', 'Succinivibrionaceae;Succinivibrio;NA', 'UGC-10;NA;NA'), 
                 classifier_c= c('Lachnospiraceae;Blautia;Blautia faecis', 'Succinivibrionaceae;Succinivibrio;Succinivibrio dextrinosolvens', 'NA;NA;NA'),
                 Row_mode=c("Lachnospiraceae;Blautia;Blautia faecis", "Succinivibrionaceae;Succinivibrio;NA","NA;NA;NA"))

在第一行创建的新Row_mode变量中,我获得了所需的输出:毛螺旋菌科;Blautia;Blautia faecis。然而,在第二行,我没有得到classifier_c得到的分类,这是唯一给我科、属和种的分类。这是正常的,因为我使用了众数概念。
因此,我需要从模式中取出一部分来考虑三个分类水平的最大化。在第二种情况下,我希望得到以下情况:

Succinivibrionaceae;Succinivibrio;Succinivibrio dextrinosolvens instead of Succinivibrionaceae;Succinivibrio;NA

最后,在第三行,我想获得NA值较小的情况,尽管它不是统计模式。
一般而言,我喜欢众数统计,因为我希望从3种分类方法中获得相似的分类谱系,但在每一行中,我希望从所比较的三种方法中的几乎一种方法中获得最长(信息量更大)的谱系。
总的来说,所需输出为:

df <- data.frame(classifier_a = c("Lachnospiraceae;Blautia;NA", 'Succinivibrionaceae;Succinivibrio;NA', 'NA;NA;NA'), 
                 classifier_b = c('Lachnospiraceae;Blautia;Blautia faecis', 'Succinivibrionaceae;Succinivibrio;NA', 'UGC-10;NA;NA'), 
                 classifier_c= c('Lachnospiraceae;Blautia;Blautia faecis', 'Succinivibrionaceae;Succinivibrio;Succinivibrio dextrinosolvens', 'NA;NA;NA'),
                 desired_output=c("Lachnospiraceae;Blautia;Blautia faecis", "Succinivibrionaceae;Succinivibrio;Succinivibrio dextrinosolvens","UGC-10;NA;NA"))

预先感谢您的帮助和提示。

krugob8w

krugob8w1#

在您的代码中,您使用which.max来查找三个分类器之间最常见的答案,这就是为什么您得到琥珀弧菌科;琥珀酸弧菌属;NA代替琥珀酸弧菌科;琥珀酸弧菌属;第2列为糊精溶解琥珀酸弧菌。
我修改了你的代码,使用which.max来查找三个分类器中最长的答案,这将对应于你在玩具例子中给出的科、属和种。

df <- data.frame(classifier_a = c("Lachnospiraceae;Blautia;NA", 'Succinivibrionaceae;Succinivibrio;NA', 'NA;NA;NA'), 
                 classifier_b = c('Lachnospiraceae;Blautia;Blautia faecis', 'Succinivibrionaceae;Succinivibrio;NA', 'UGC-10;NA;NA'), 
                 classifier_c= c('Lachnospiraceae;Blautia;Blautia faecis', 'Succinivibrionaceae;Succinivibrio;Succinivibrio dextrinosolvens', 'NA;NA;NA'))

df$Row_mode <- apply(df, 1, function(x) {x[which.max(nchar(x))]})
df

该函数返回:

classifier_a                           classifier_b                                                    classifier_c
1           Lachnospiraceae;Blautia;NA Lachnospiraceae;Blautia;Blautia faecis                          Lachnospiraceae;Blautia;Blautia faecis
2 Succinivibrionaceae;Succinivibrio;NA   Succinivibrionaceae;Succinivibrio;NA Succinivibrionaceae;Succinivibrio;Succinivibrio dextrinosolvens
3                             NA;NA;NA                           UGC-10;NA;NA                                                        NA;NA;NA
                                                         Row_mode
1                          Lachnospiraceae;Blautia;Blautia faecis
2 Succinivibrionaceae;Succinivibrio;Succinivibrio dextrinosolvens
3                                                    UGC-10;NA;NA
6pp0gazn

6pp0gazn2#

更新答案(说明多个最小值,备注中的数据集):

least_na <- function(x){
  index <- stringr::str_count(x,"NA")
  paste(x[which(index==min(index))],collapse="|")
}
df_2$Row_mode <- apply(df_2,1,least_na)

> df_2$Row_mode
[1] "Lachnospiraceae;Blautia;Blautia faecis|Lachnospiraceae;Escherichia;Escherichia coli"

我们可以为此创建用户定义函数:

least_na <- function(x){
  x[which.min(str_count(x,"NA"))]
}

df$Row_mode <- apply(df,1,least_na)

> df$Row_mode
[1] "Lachnospiraceae;Blautia;Blautia faecis"                         
[2] "Succinivibrionaceae;Succinivibrio;Succinivibrio dextrinosolvens"
[3] "UGC-10;NA;NA"
8dtrkrch

8dtrkrch3#

df %>%
  rowid_to_column()%>%
  separate_rows(everything(), sep = ';') %>%
  mutate(new_col = do.call('coalesce', across(-1, ~na_if(.,'NA'))),
         new_col = replace_na(new_col, 'NA'))%>%
  group_by(rowid) %>%
  summarise(across(everything(), ~str_c(.x, collapse = ';')))

相关问题