File: parafit.R

package info (click to toggle)
r-cran-ape 5.8-1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,676 kB
  • sloc: ansic: 7,676; cpp: 116; sh: 17; makefile: 2
file content (161 lines) | stat: -rw-r--r-- 5,195 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
'parafit' <-
	function(host.D, para.D, HP, nperm=999, test.links=FALSE, seed=NULL, correction="none", silent=FALSE)
#
# Test of host-parasite coevolution
# host.D = host distance or patristic matrix (class dist or matrix)
# para.D = parasite distance or patristic matrix (class dist or matrix)
# HP = host-parasite link matrix (n.host, n.para)
#
#      Pierre Legendre, May 2009
{
epsilon <- sqrt(.Machine$double.eps)
if(is.null(seed)) {
	runif(1)
	seed <- .Random.seed[trunc(runif(1,1,626))]
	}
HP <- as.matrix(HP)

host.D <- as.matrix(host.D)
host.pc <- pcoa(host.D, correction=correction)
if(host.pc$correction[2] == 1) {
	if(min(host.pc$values[,2]) < -epsilon) stop('Host D matrix has negative eigenvalues. Rerun with correction="lingoes" or correction="cailliez"')
	sum.host.values.sq <- sum(host.pc$values[,1]^2)
	host.vectors <- host.pc$vectors
	} else {
	sum.host.values.sq <- sum(host.pc$values[,2]^2)
	host.vectors <- host.pc$vectors.cor
	}
n.host <- nrow(host.D)

para.D <- as.matrix(para.D)
para.pc <- pcoa(para.D, correction=correction)
if(para.pc$correction[2] == 1) {
	if(min(para.pc$values[,2]) < -epsilon) stop('Parasite D matrix has negative eigenvalues. Rerun with correction="lingoes" or correction="cailliez"')
	sum.para.values.sq <- sum(para.pc$values[,1]^2)
	para.vectors <- para.pc$vectors
	} else {
	sum.para.values.sq <- sum(para.pc$values[,2]^2)
	para.vectors <- para.pc$vectors.cor
	}
n.para <- nrow(para.D)

if(!silent) cat("n.hosts =", n.host, ", n.parasites =", n.para,'\n')

a <- system.time({
tracemax <- max(sum.host.values.sq, sum.para.values.sq)

if(n.host == n.para) {
	if(!silent) cat("The function cannot check if matrix HP has been entered in the right way.",'\n')
	if(!silent) cat("It will assume that the rows of HP are the hosts.",'\n')
	} else {
	temp <- dim(HP)
	if(temp[1] == n.host) {
		if(temp[2] != n.para) stop("Matrices host.D, para.D and HP not comformable")
		} else if(temp[2] == n.host) {
			if(temp[1] != n.para) stop("Matrices host.D, para.D and HP not comformable")
			HP <- t(HP)
			if(!silent) cat("Matrix HP has been transposed for comformity with host.D and para.D.",'\n')
		} else {
		stop("Matrices host.D, para.D and HP not comformable")
		}
	}
p.per.h <- apply(HP, 1, sum)
h.per.p <- apply(HP, 2, sum)
#
# Compute and test the global statistics
mat.4 <- t(host.vectors) %*% HP %*% para.vectors
global <- sum(mat.4^2)
if(nperm > 0) {
	set.seed(seed)
	nGT <- 1
	global.perm <- NA
	for(i in 1:nperm) {
		HP.perm <- apply(HP, 2, sample)
		mat.4.perm <- t(host.vectors) %*% HP.perm %*% para.vectors
		global.perm <- c(global.perm, sum(mat.4.perm^2))
		if(global.perm[i+1] >= global) nGT <- nGT+1
		}
	global.perm <- global.perm[-1]
	p.global <- nGT/(nperm+1)
	} else { p.global <- NA }

#
# Test individual H-P links
if(test.links) {
	# 1. Create the list of H-P pairs
	list.hp <- which( t(cbind(HP,rep(0,n.host))) > 0)
	HP.list <- cbind((list.hp %/% (n.para+1))+1, list.hp %% (n.para+1))
	colnames(HP.list) <- c("Host","Parasite")
	n.links <- length(list.hp)

	stat1 <- NA
	stat2 <- NA
	p.stat1 <- NA
	p.stat2 <- NA
	for(k in 1:n.links) {
		#
		# 2. Compute reference values of link statistics
		HP.k <- HP
		HP.k[HP.list[k,1], HP.list[k,2]] <- 0
		mat.4.k <- t(host.vectors) %*% HP.k %*% para.vectors
		trace.k <- sum(mat.4.k^2)
		stat1 <- c(stat1, (global-trace.k))
		den <- tracemax-global
		if(den > epsilon) {
			stat2 <- c(stat2, stat1[k+1]/den)
			} else {
			stat2 <- c(stat2, NA)
			}
		#
		# 3. Test link statistics by permutations
		if(nperm > 0) {
			set.seed(seed)
			nGT1 <- 1
			nGT2 <- 1
			nperm2 <- nperm
			#
			for(i in 1:nperm) {
				HP.k.perm <- apply(HP.k, 2, sample)
				mat.4.k.perm <- t(host.vectors) %*% HP.k.perm %*% para.vectors
				trace.k.perm <- sum(mat.4.k.perm^2)
				stat1.perm <- global.perm[i]-trace.k.perm
				if(stat1.perm >= stat1[k+1]) nGT1 <- nGT1+1
				#
				if(!is.na(stat2[k+1])) {
					den <- tracemax-global.perm[i]
					if(den > epsilon) {
						stat2.perm <- stat1.perm/den
						if(stat2.perm >= stat2[k+1]) nGT2 <- nGT2+1
						} else {
						nperm2 <- nperm2-1
						# if(!silent) cat("In permutation #",i,"den < epsilon",'\n')
						}
					}
				}
			p.stat1 <- c(p.stat1, nGT1/(nperm+1))
			if(!is.na(stat2[k+1])) {
				p.stat2 <- c(p.stat2, nGT2/(nperm2+1))
				} else {
				p.stat2 <- c(p.stat2, NA) ### Error in previous version, corrected here
				}
			} else {
			p.stat1 <- c(p.stat1, NA)     ### Error in previous version, corrected here
			p.stat2 <- c(p.stat2, NA)     ### Error in previous version, corrected here
			}
		}
	#
	link.table <- cbind(HP.list, stat1[-1], p.stat1[-1], stat2[-1], p.stat2[-1])
	colnames(link.table) = c("Host","Parasite","F1.stat","p.F1","F2.stat","p.F2")
	out <-list(ParaFitGlobal=global, p.global=p.global, link.table=link.table, para.per.host=p.per.h, host.per.para=h.per.p, nperm=nperm)
	} else {
	if(!silent) cat("Rerun the program with option 'test.links=TRUE' to test the individual H-P links",'\n')
	out <-list(ParaFitGlobal=global, p.global=p.global, para.per.host=p.per.h, host.per.para=h.per.p, nperm=nperm)
	}
#
})
a[3] <- sprintf("%2f",a[3])
if(!silent) cat("Computation time =",a[3]," sec",'\n')
#
class(out) <- "parafit"
out
}