R,如何在apply函数中添加unlist(和其他)函数?

时间:2016-07-19 14:44:07

标签: r dataframe apply strsplit

背景:我正在研究基因和本体,但我的问题是关于R脚本的写作。

我想用数据库中提取的相应术语替换数据框中的GO:ID。

所以,这是我的源数据框架。它是一个基因列表(v1)和相关的GO:ID(v2):

>gene_list_and_Go_ID

         V1                                                V2
2563  Gene1    GO:0003871, GO:0008270, GO:0008652, GO:0009086
2580  Gene2    GO:0003871, GO:0008270, GO:0008652, GO:0009086
12686 Gene3    GO:0003871, GO:0008270, GO:0008652, GO:0009086
14523 Gene4                GO:0004489, GO:0006555, GO:0055114

对数据库的请求看起来很简单:

>select(GO.db, my_Go_id, "TERM", "GOID")

我尝试了以下几行来手动处理数据库,它运行良好:

>my_Go_id = unlist(strsplit("GO:0008270, GO:0008652, GO:0009086", split=", "))
>select(GO.db, my_Go_id, "TERM", "GOID")

    GOID                                     TERM
1 GO:0008270                         zinc ion binding
2 GO:0008652 cellular amino acid biosynthetic process
3 GO:0009086          methionine biosynthetic process

我的问题:我无法自动完成此过程! 确切地说,对于每一行,我需要将每个字符串从我的数据帧中的第n°2列转换为向量,以便对数据库提出质疑。 然后我需要用请求的结果替换数据框中的GO:ID。

1 /为了开始,我尝试将“unlist”功能放入“应用”功能到我的数据框:

apply(gene_list_and_Go_ID,1,unlist(strsplit(gene_list_and_Go_ID[,2], split=", ")))

我得到了:

Error in strsplit(ok, split = ", ") : non-character argument

2 /然后,我可以将请求添加到apply函数中的数据库吗?

3 /最后,我不知道如何用数据库请求的结果替换n°2列。

这是一个例外的“理想”结果的例子:

         V1                                                              V2
2563  Gene1        GOID                                                TERM
                   1 GO:0008270                            zinc ion binding
                   2 GO:0008652    cellular amino acid biosynthetic process
                   3 GO:0009086             methionine biosynthetic process

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

最近的问题是你不像你那样打电话给apply。你没有像你那样编写一个函数调用,而是需要提供一个函数,它将数组的每一行/列依次作为输入通过它的第一个参数,所以你需要类似的东西(未经过测试) ,因为你不需要这个)

apply(gene_list_and_Go_ID, 1,
      function(x) { unlist(strsplit(x[2], split=", "))})

但请注意,您不需要gene_list_and_Go_ID的完整。您想要的是处理V2的{​​{1}} 。现在还要注意gene_list_and_Go_ID vectorised ,这意味着如果你传递一个长度大于1的向量,它将对该向量的每个元素起作用,就像你反复调用{{依次对矢量的每个元素进行1}}。

请考虑以下事项:

strsplit

请注意strsplit()需要是一个字符向量---在这里我使用df <- data.frame(V1 = paste0("Gene", 1:4), V2 = c("GO:0003871, GO:0008270, GO:0008652, GO:0009086", "GO:0003871, GO:0008270, GO:0008652, GO:0009086", "GO:0003871, GO:0008270, GO:0008652, GO:0009086", "GO:0004489, GO:0006555, GO:0055114"), stringsAsFactors = FALSE) 来停止自动强制V2 - &gt; stringsAsFactors = FALSE,但您也可以在下面的代码中使用character factor

要在as.character(V2)的每个元素上运行V2,我们可以使用:

strsplit

让我们

V2

通过spl <- with(df, strsplit(V2, ", ")) 来电,这是一次性的交易 - 您需要为> spl [[1]] [1] "GO:0003871" "GO:0008270" "GO:0008652" "GO:0009086" [[2]] [1] "GO:0003871" "GO:0008270" "GO:0008652" "GO:0009086" [[3]] [1] "GO:0003871" "GO:0008270" "GO:0008652" "GO:0009086" [[4]] [1] "GO:0004489" "GO:0006555" "GO:0055114" (您的select)中的所有行调用它。如果是这样,只需迭代df返回的列表元素:

gene_list_and_Go_ID

这将返回一个列表,其中每个元素是对strsplit()的单个基因/行调用names(spl) <- with(df, as.character(V1)) term <- lapply(spl, function(x, db) select(db, x, "TERM", "GOID"), db = GO.db) 的结果。

将它重新组合在一起你可能想要:

select

但我无法测试最后几个部分,因为我不知道df来自哪里,创造了什么out <- cbind.data.frame(Gene = rep(names(spl), each = lengths(spl)), do.call("rbind", term))

答案 1 :(得分:0)

好的,根据Gavin的回答和他的帮助,我得到了正确的剧本。但是有一个非常重要的步骤阻止了我:将我的“gene_list_and_Go_ID”数据框第二列从因子转换为字符。我这样做是为了跳过“strsplit”函数中的“非字符参数”错误。这篇文章帮助了我:LINK

所以这是我的起始数据框:

unless Rails.env == 'production'

接下来是脚本。 第一个新行似乎非常有用(将我的df从因子转换为字符):

>gene_list_and_Go_ID

         V1                                                V2
2563  Gene1    GO:0003871, GO:0008270, GO:0008652, GO:0009086
2580  Gene2    GO:0003871, GO:0008270, GO:0008652, GO:0009086
12686 Gene3    GO:0003871, GO:0008270, GO:0008652, GO:0009086
14523 Gene4                GO:0004489, GO:0006555, GO:0055114

下:

>gene_list_and_Go_ID <- data.frame(lapply(gene_list_and_Go_ID, as.character), stringsAsFactors=FALSE)

最终输出是完美的:-):

>V_ID <- with(gene_list_and_Go_ID, strsplit(V2, ", "))
>names(V_ID) <- with(gene_list_and_Go_ID, as.character(V1))
>terms <- lapply(V_ID, function(x, db) select(db, x, "TERM", "GOID"), db = GO.db)

注意,我跳过了最后一个Gavin的建议:

> terms
$Gene1
        GOID                        TERM
1 GO:0003871 S-methyltransferase activity
2 GO:0008270 zinc ion binding
3 GO:0008652 cellular amino acid biosynthetic process
4 GO:0009086 methionine biosynthetic process

$Gene2
... etc ...
... etc ...

这可能是一个非常优雅的剧本,但我很难理解它的作用,以及它产生的内容:

out <- cbind.data.frame(Gene = rep(names(spl), each = lengths(spl)),
                    do.call("rbind", term))

THX