在R中创建一个函数

时间:2016-03-13 04:09:12

标签: r csv bioinformatics

我试图创建查看两个CSV文件的代码:一个是所有鸟类及其范围的世界列表,另一个是喜马拉雅山脉中所有鸟类的文件。我需要检查CSV文件中的每个物种与IOC世界列表中的匹配物种,并查看该鸟是否实际上在范围内(意味着它会说"India""himalayas"或{{1 } {在"s e Asia"列下)。我想创建一个可以输入两个数据集的函数,查找名称匹配的位置,检查范围是否包含这些单词并返回它不存在的位置,这样我就可以专门检查这些鸟类。这是我到目前为止(我使用Range):

RStudio

我想我没有投入就搞砸了。所以我尝试了一种新方法:

myfunc <- function() { 

if ((bird_data$Scientific.name == ioc$Scientific.name) &      (ioc$Scientific.name!=("Himalayas" | "se Asia" | "India")) {
print(eval(bird_data$Common.Name[bird_data$Scientific.name == ioc$Scientific.name) & (ioc$Scientific.name!=("Himalayas" | "se Asia" | "India")]))
  }
}
save("myfunc", file = "myfunc.Rdata")  
source("myfunc.Rdata")

但是对于上述情况,我不知道如何让函数识别出合适的数据子集(就像我不能说compare = function(data1, data2) { .... } )。

1 个答案:

答案 0 :(得分:2)

如果没有最小的可重复示例,很难回答这个问题 - 如果不了解您所比较的两个数据框架很难制定解决方案 - 请参阅上面alistaire的评论中的链接,了解如何提供这个。

我建议您更改问题标题以使其更具信息性 - “在R中创建函数”表示您想知道R中函数所需的语法 - 我建议“使用Grep子集化数据帧然后过滤结果在R“ - 这是我认为你实际上想要做的。

假设您从国际鸟类委员会website获得了您的IOC世界列表数据,我不确定您在函数中描述的方法是否可以作为育种范围 - 子区域列中的数据工作非常混乱,例如:

w Himalayas to s Siberia and w Mongolia
Himalayas to c China
e Afghanistan to nw India and w Nepal
e Afghanistan to w Tibetan plateau and n India
Africa south of the Sahara, s and se Asia

这些值中没有一个与“India”或“himalayas”或“SE Asia”相同,并且您的函数不会返回任何值以查找完全匹配。您需要使用grep来查找数据中存在的子字符串。

让我们创建一个玩具数据集。

bird_data <- data.frame(
        Scientific.name=c(
          "Chicken Little",
          "Woodstock",
          "Woody Woodpecker",
          "Donald Duck",
          "Daffy Duck",
          "Big Bird",
          "Tweety Pie",
          "Foghorn Leghorn",
          "The Road Runner",
          "Angry Birds"))

ioc_data <- data.frame(
  Scientific.name=c(
          "Chicken Little",
          "Woodstock",
          "Woody Woodpecker",
          "Donald Duck",
          "Daffy Duck",
          "Big Bird",
          "Tweety Pie",
          "The Road Runner",
          "Angry Birds"),
  subrange=c(
    "Australia, New Zealand",
    "w Himalayas to s Siberia and w Mongolia",
    "Himalayas to c China",
    "e Afghanistan to nw India and w Nepal",
    "e Afghanistan to w Tibetan plateau and n India",
    "Africa south of the Sahara, s and se Asia",
    "Amazonia to n Argentina",
    "n Eurasia",
    "n North America"))

我会把你要做的事情分成两步。

第1步

根据您的搜索字词是否在子范围列中找到,使用grep对ioc_data数据框进行子集化:

searchTerms <- c("India", "himalayas", "SE Asia")

#Then we use grep to return the indexes of matching rows:

matchingIndexes <- grep(paste(searchTerms, collapse="|"), 
                        ioc_data$subrange,
                        ignore.case=TRUE) #Important so search such as "SE Asia" will match "se asia"

#We can then use our matching indexes to subset our ioc_data dataframe producing
#a subset of data corresponding to our range of interest:

ioc_data_subset <- ioc_data[matchingIndexes,]

第2步

如果我正确理解你的问题,你现在想要从bird_data中提取ioc_data_subset中不存在的行(即,bird_data中的哪些行是针对未记录为居住在“印度”,“东南亚”子范围内的鸟类和IOC数据中的“喜马拉雅山”。

我会使用Hadley Wickham的dplyr软件包 - 可以找到一份好的备忘单here。安装dplyr后:

library(dplyr)

#Create a merged dataframe containing all the data in one place.
merged_data <- dplyr::left_join(bird_data,
                ioc_data,
                by = "Scientific.name")

#Use an anti_join to select any rows in merged_data that are NOT present in
#ioc_data_subset

results <- dplyr::anti_join(merged_data,
                ioc_data_subset,
                by = "Scientific.name")

首先需要left_join,否​​则我们不会在最终数据库中拥有子范围列。请注意,不在IOC_data中的bird_data中的任何物种都将在子范围列中返回NA,以指示未找到任何数据。

 results
  Scientific.name                subrange
1     Angry Birds         n North America
2 The Road Runner               n Eurasia
3 Foghorn Leghorn                    <NA>
4      Tweety Pie Amazonia to n Argentina
5  Chicken Little  Australia, New Zealand