这是一个很重要的问题,但我会尽力解释。我正在尝试编写一个程序,跟踪昆虫随着时间的推移访问了一种花的次数。为此,我有一个看起来像这样的数据集:
ID Visit_Freq Visitor_1 Visitor_2 Visitor_3 Visitor_4 Visitor_5
1 1.0000000 Halictidae <NA> <NA> <NA> <NA>
2 5.0000000 Syrphidae Halictidae Syrphidae Syrphidae Apis
3 1.0000000 Apis <NA> <NA> <NA> <NA>
4 0.0000000 <NA> <NA> <NA> <NA> <NA>
5 0.0000000 <NA> <NA> <NA> <NA> <NA>
6 0.0000000 <NA> <NA> <NA> <NA> <NA>
7 0.0000000 <NA> <NA> <NA> <NA> <NA>
8 2.0000000 Apis Apis <NA> <NA> <NA>
9 0.0000000 <NA> <NA> <NA> <NA> <NA>
10 0.0000000 <NA> <NA> <NA> <NA> <NA>
在“Visitor_n”栏目下,我记录了一种曾经访问该花的昆虫,或者没有访问过的NA。为了分析我们的数据,我们必须在每个访客列中计算每种昆虫类型。有时我们可以有多达10个访客花(ID),我们的ID数通常超过500,所以手工计算事件可能是一件苦差事。以下是我为简化工作所做的工作:
Apis <- sum(apply(DataSet[3:7], 2, function(x) length(which(x == 'Apis'))))
到目前为止,上面的这行已经很好地计算了Apis在我的真实数据集中出现的次数,但问题是有几十种昆虫类型可能会或可能不会访问我们的植物,所以到为了安全起见,我必须有大约30-50个类似的代码行,每个代码都用不同的昆虫类型代替“Apis”...例如......
Apis <- sum(apply(DataSet[3:7], 2, function(x) length(which(x == 'Apis'))))
Bombus <- sum(apply(DataSet[3:7], 2, function(x) length(which(x == 'Bombus'))))
Halictidae <- sum(apply(DataSet[3:7], 2, function(x) length(which(x == 'Halictidae'))))
Syrphidae <- sum(apply(DataSet[3:7], 2, function(x) length(which(x == 'Syrphidae'))))
Skipper <- sum(apply(DataSet[3:7], 2, function(x) length(which(x == 'Skipper'))))
等等。
如果我能找到一种方法让R自动识别“昆虫A,B,D,F和H出现在列[3:7]中,这将是非常有用的,这是他们的次数例如,所有这些都发生在一起,而不是必须输入每条昆虫的30-50行,以确保我没有遗漏任何东西。
我并不反对安装包来做这件事,但如果可能的话,我想尽可能保持它与基地R尽可能接近。我想向一些几乎没有R经验的实验室伙伴介绍这个。
昨晚我确实问了一个类似的问题,但从那时起我已经取得了一些进展。
答案 0 :(得分:3)
此解决方案假设您的昆虫名称仅包含英文字母且没有数字,第一个字母为大写,剩余部分为小写。
data.frame(table(grep("[A-Z]{1}[a-z]+",stack(df1)[,1],value=TRUE)))
Var1 Freq
1 Apis 4
2 Halictidae 2
3 Syrphidae 3
df1<-
structure(list(ID = 1:10, Visit_Freq = c(1, 5, 1, 0, 0, 0, 0,
2, 0, 0), Visitor_1 = c("Halictidae", "Syrphidae", "Apis", "<NA>",
"<NA>", "<NA>", "<NA>", "Apis", "<NA>", "<NA>"), Visitor_2 = c("<NA>",
"Halictidae", "<NA>", "<NA>", "<NA>", "<NA>", "<NA>", "Apis",
"<NA>", "<NA>"), Visitor_3 = c("<NA>", "Syrphidae", "<NA>", "<NA>",
"<NA>", "<NA>", "<NA>", "<NA>", "<NA>", "<NA>"), Visitor_4 = c("<NA>",
"Syrphidae", "<NA>", "<NA>", "<NA>", "<NA>", "<NA>", "<NA>",
"<NA>", "<NA>"), Visitor_5 = c("<NA>", "Apis", "<NA>", "<NA>",
"<NA>", "<NA>", "<NA>", "<NA>", "<NA>", "<NA>")), .Names = c("ID",
"Visit_Freq", "Visitor_1", "Visitor_2", "Visitor_3", "Visitor_4",
"Visitor_5"), row.names = c(NA, -10L), class = "data.frame")
答案 1 :(得分:1)
使用我们的昆虫名称创建一个载体
insects <- c( "Apis", "Halictidae", "Syrphidae" )
您也可以使用
自动获取此信息insects <- unique( unlist( DataSet[ 3:7 ] ) )
insects <- insects[ -( which ( insects == "<NA>" ) ) ]
然后创建一个获取访问次数的空变量
count <- NULL
然后你可以继续使用你拥有的东西,然后循环遍历昆虫的名字
for( i in insects )
count <- c( count, sum( apply( DataSet[ 3:7 ], 2,
function( x ) length( which( x == i) ) ) ) )
count
[1] 4 2 3
如果您愿意,可以将两者结合起来
insectCount <- data.frame( insects, count )
insectCount
insects count
1 Apis 4
2 Halictidae 2
3 Syrphidae 3
请注意,昆虫的顺序会有所不同,具体取决于您是手动还是自动创建矢量。在任何一种情况下,计数都是相同的。
答案 2 :(得分:0)
我喜欢这些问题dplyr
,因为一旦数据采用正确(整洁)的格式,问题就可以在一行中解决。要将数据转换为整洁格式,我们还需要一行(使用包gather()
中的tidyr
)。
我正在使用user227710定义的数据框here.请注意,它包含字符串&#34;&lt; NA&gt;&#34;而不是适当的R NA,所以过滤掉NA的线看起来有点奇怪。
实际工作由函数group_by()
和tally()
完成。您告诉R如何对数据进行分组(此处为Species
变量),然后tally()
对其进行计数。
我理解,您并不想使用外部软件包,但学习如何使用tidyr
和dplyr
对于定期处理数据的人来说绝对值得。
require(tidyr) # for gather()
require(dplyr) # for group_by() and tally()
# convert table into tidy (long) format
df_long <- gather(df1, Visitor, Species, Visitor_1:Visitor_5)
head(df_long)
## ID Visit_Freq Visitor Species
## 1 1 1 Visitor_1 Halictidae
## 2 2 5 Visitor_1 Syrphidae
## 3 3 1 Visitor_1 Apis
## 4 4 0 Visitor_1 <NA>
## 5 5 0 Visitor_1 <NA>
## 6 6 0 Visitor_1 <NA>
# now count species, excluding the <NA> value
group_by(df_long, Species) %>%
filter(Species != "<NA>") %>%
tally()
## Source: local data frame [3 x 2]
##
## Species n
## 2 Apis 4
## 3 Halictidae 2
## 4 Syrphidae 3