首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >R,如何在apply函数中添加unlist (和其他)函数?

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

Stack Overflow用户
提问于 2016-07-19 22:44:07
回答 2查看 1.1K关注 0票数 1

上下文:我正在处理基因和本体,但我的问题与R脚本编写有关。

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

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

代码语言:javascript
复制
>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

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

代码语言:javascript
复制
>select(GO.db, my_Go_id, "TERM", "GOID")

我尝试了以下几行代码来手动访问数据库,它工作得很好:

代码语言:javascript
复制
>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”函数中,以应用到我的数据框中:

代码语言:javascript
复制
apply(gene_list_and_Go_ID,1,unlist(strsplit(gene_list_and_Go_ID[,2], split=", ")))

我得到了:

代码语言:javascript
复制
Error in strsplit(ok, split = ", ") : non-character argument

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

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

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

代码语言:javascript
复制
         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

谢谢你的帮助。

EN

回答 2

Stack Overflow用户

发布于 2016-07-19 23:07:34

最直接的问题是,您没有像以前那样调用apply。与您编写函数调用不同,您需要提供一个函数,该函数将通过其第一个参数依次获取数组的每一行/每一列作为输入,因此您需要类似于(未测试,因为您不需要它)的内容。

代码语言:javascript
复制
apply(gene_list_and_Go_ID, 1,
      function(x) { unlist(strsplit(x[2], split=", "))})

但是,请注意,您不需要整行的gene_list_and_Go_ID。您想要的是处理gene_list_and_Go_IDV2列。现在还要注意,strsplit是矢量化的,这意味着如果你向它传递一个长度大于1的向量,它将对该向量的每个元素起作用,就像你依次对该向量的每个元素重复调用strsplit()一样。

请考虑以下几点:

代码语言:javascript
复制
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需要是一个字符向量-这里我使用stringsAsFactors = FALSE来停止自动强制character -> factor,但您也可以在下面的代码中使用as.character(V2),其中我有V2

要在V2的每个元素上运行strsplit,我们可以使用:

代码语言:javascript
复制
spl <- with(df, strsplit(V2, ", "))

这让我们

代码语言:javascript
复制
> 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()返回的列表元素

代码语言:javascript
复制
names(spl) <- with(df, as.character(V1))
term <- lapply(spl, function(x, db) select(db, x, "TERM", "GOID"),
               db = GO.db)

这将返回一个列表,其中每个元素都是针对df的单个基因/行调用select的结果。

把它放回原处,你可能需要:

代码语言:javascript
复制
out <- cbind.data.frame(Gene = rep(names(spl), each = lengths(spl)),
                        do.call("rbind", term))

但是我不能测试最后几个部分,因为我不知道select()是从哪里来的,也不知道是什么创造了GO.db

票数 2
EN

Stack Overflow用户

发布于 2016-07-20 17:17:16

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

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

代码语言:javascript
复制
>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

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

代码语言:javascript
复制
>gene_list_and_Go_ID <- data.frame(lapply(gene_list_and_Go_ID, as.character), stringsAsFactors=FALSE)

接下来:

代码语言:javascript
复制
>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)

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

代码语言:javascript
复制
> 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 ...

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

代码语言:javascript
复制
out <- cbind.data.frame(Gene = rep(names(spl), each = lengths(spl)),
                    do.call("rbind", term))

这可能是一个非常优雅的脚本,但我很难理解它的所有功能,下面是它生成的内容:

代码语言:javascript
复制
Error in data.frame(..., check.names = FALSE) : 
  arguments imply differing number of rows: 16, 15
In addition: Warning message:
In rep(names(V_ID), each = lengths(V_ID)) :
  first element used of 'each' argument

THX

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38461731

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档