FSO is a different approach to the ordination of vegetation data. It
was introduced by Roberts (1986) as a heuristic alternative to
traditional ordination techniques. Unlike these latter techniques, an
investigator using fuzzy set ordination must hypothesize a relationship
between the environment and the vegetation before performing the
ordination. Sites are assigned values that can range from 0 to 1 that
denote their membership in a set. For example, the values of site in a
fuzzy set of "high elevations" would range from 0 (the lowest site) to
1 (the highest site). Conversely, the values of sites in a
lowelevation fuzzy set would range from 0 (the highest site) to 1 (the
lowest site). The sets are considered to be fuzzy because each site or
element in the set can have partial membership; in classical set
theory, elements are either completely in or completely out of a given
set. The operations of classical set theory, such as union and
intersection, can also be performed on fuzzy sets. One very useful
operator in vegetation analysis is the anticommutative difference
(Roberts 1986), which can be understood as "while not." This can be
used, for example, to construct a fuzzy set that includes the
membership of sites that are similar in composition to high elevation
sites while not actually at high elevation.
Roberts (1986) has shown that fuzzy set ordination is a general
technique that includes specific types of ordination that ecologists
are
more familiar with, such as direct gradient analysis (Whittaker 1967),
BrayCurtis ordination (Bray & Curtis 1957), and environmental
scalars ordination (Loucks 1962). Species responses to environmental
factors are not restricted to any particular function; they can be, for
example, nonlinear or discontinuous. Also, each axis of the ordination
is chosen beforehand, so the basis of interpretation is predetermined.
Thus, the ecologist can use fuzzy set ordination to explicitly test
hypotheses. So FSO, like RDA and CCA, is a constrained or direct
ordination technique; in fact, FSO is the constrained version of
BrayCurtis (polar) ordination, the grandaddy of all ordination
techniques.
While software packages have been developed for many ordination
techniques, few exist for FSO. MULVA5 for
Macintosh
and Windows is one that I'm aware of that incorporates an FSO routine
(FUZZORD). It also incorporates a stepacross routine (FSPATH) to
remove horseshoe/curlover effects (read below to find out more about
that). However, your choice of similarity indices in MULVA5 is
limited,
and it matters a great deal (see below) as to which similarity index is
used.
I originally developed SAS code to perform FSO. However, I no
longer have access to SAS. You can click here to use
the archived SAS material, but be aware that I no longer maintain
it, and it is not completely uptodate. Also, it is rather
slow...
Distance
Index 
Formula* 
Boyce** 
labdsv 
vegan 

BaroniUrbani
& Buser 
(a
+ sqrt(a*d))/(a + b + c + sqrt(a*d)) 
√ 

Jaccard 
a/(a + b + c)  √ 
√ 

Kulczynski 
0.5* (a/(a +
b) + a/(a + c)) 
√ 
√ 

Ochiai 
a/sqrt((a +
b) * (a + c)) 
√ 
√ 

Sørensen 
2 * a/(2 * a
+ b + c) 
√ 
√ 
Distance Index 
Formula* 
Boyce** 

BaroniUrbani
& Buser 
√ 

Horn 
√ 

Yule*** 
√ 
library(labdsv)I've already formatted the data as presence/absence data, i.e., if a species is present at a site, it is given a 1, and if absent, a 0. If your data are given as abundances and you want to convert it to presence/absence, include the following line:
library(fso)
veg < read.table("goliathveg.txt",header=T, sep="\t")
site < read.table("goliathsite.txt",header=T,sep="\t")
veg[veg > 0] < 1To compute a distance matrix, use following function, which I've adapted from dist.binary in the R library ade4 (note that this may be downloaded as binarysim.R.
sim.binary < function (df, method = NULL, diag=FALSE, upper=FALSE){This creates a function that will calculate a similarity matrix of the form required by fso(). I've included the 5 indices recommended by Boyce and Ellison (2001). Since we used Sørensen's index for this study, let's go ahead and do this. We will then convert the similarity index into a distance index, which is also required by fso():
df < as.matrix(df)
a < df %*% t(df)
b < df %*% (1  t(df))
c < (1  df) %*% t(df)
d < ncol(df)  a  b  c
#1=Jaccard, 2=BaroniUrbani & Buser, 3=Kulczynski, 4=Ochiai, 5=Sorensen
if (method == 1) {
sim < a/(a + b + c)
}
else if (method == 2) {
sim < (a + sqrt(a*d))/(a + b + c + sqrt(a*d))
}
else if (method == 3) {
sim < 0.5* (a/(a + b) + a/(a + c))
}
else if (method == 4) {
sim < a/sqrt((a + b) * (a + c))
}
else if (method == 5) {
sim < 2 * a/(2 * a + b + c)
}
sim2 < sim[row(sim) > col(sim)]
class(sim2) < "dist"
attr(sim2, "Labels") < dimnames(df)[[1]]
attr(sim2, "Diag") < diag
attr(sim2, "Upper") < upper
attr(sim2, "Size") < nrow(df)
attr(sim2, "call") < match.call()
return(sim2)
}
#Change method number to the similarity index you want to useWe will use the attach command so that we can refer to individual variables in site without having to use the site$ prefix:
sim < sim.binary(veg,method=5)
dis.sor < 1  sim
attach(site)We will start by performing FSO on elevation, which often is an important variable.
elev.fso < fso(elev,dis.sor)
elev.fso
plot(elev.fso, title = "Mt. Goliath", xlab="Actual Elevation", ylab="Apparent Elevation")
elev.fso < fso(elev,dis.sor, permute=1000)Let's look at the other factors examined by Boyce and Ellison (1998), which includes av (aspect value), sicl (silt + clay soil fraction), and snow (snow depth):
av.fso < fso(av,dis.sor)
av.fso
plot(av.fso)
sicl.fso < fso(sicl,dis.sor)
sicl.fso
plot(sicl.fso)
snow.fso < fso(snow,dis.sor)
snow.fso
plot(snow.fso)
grads.fso < fso(~av+elev+hl+sicl+slope+snow+pH+X.C+X.N+C.N, dis.sor)
summary(grads.fso)
col variable r p*Where hl = heat load (estimated from aspect and slope), X.C (%C in soil), X.N(%N in soil, and C.N (C:N soil ratio).
1 2 elev 0.7284380 4.203349e11
2 3 hl 0.7013599 9.598198e10
3 1 av 0.6887476 1.736076e09
4 8 X.C 0.5759182 4.382177e08
5 9 X.N 0.5709465 2.784349e09
6 6 snow 0.5368028 7.619472e06
7 10 C.N 0.5114200 2.670224e05
8 5 slope 0.4314090 6.907113e05
9 7 pH 0.4056518 5.709669e04
10 4 sicl 0.1346999 2.388193e02
grads.fso < fso(~ elev+av+sicl+snow, dis.sor, permute=1000)So elevation, aspect value and snow depth all explain variation in the plant community, while soil texture does not.
summary(grads.fso)
col variable r p
1 1 elev 0.7309908 0.001
2 2 av 0.6869921 0.001
3 4 snow 0.5399591 0.001
4 3 sicl 0.1503474 0.126
grads.mfso < mfso(~ elev+av+snow, dis.sor, scaling=2, permute=1000)
summary(grads.mfso)
plot(grads.mfso,dis.sor)
variable r p gamma
1 elev 0.7309908 0.001 1.00000000
2 av 0.6985632 0.001 0.97671766
3 snow 0.2402497 0.001 0.09013415
library(labdsv)To compute a distance matrix, use following function (also downloadable as abundsim.R). I'll be the first to admit that this function is not written in the most efficient manner, and it is slow. If you have more proficiency in R programming, feel free to write a new one, and I'll post it here.
library(fso)
veg < read.table("bryceveg.s",header=T)
site < read.table("brycesit.s",header=T)
sim.abund < function (df, method = NULL, diag = FALSE, upper = FALSE)As in the binary case, this will calculate a similarity matrix,of the form required by fso(). I've included the 3 indices I recommend. For this example, I'll use Horn's index (method = 2; BaroniUrbani and Buser is 1, and Yule is 3). Also, we will convert the similarity index into a distance index, which is also required by fso():
{
METHODS < c("BaroniUrbani & Buser", "Horn", "Yule (Modified)")
if (!inherits(df, "data.frame"))
stop("df is not a data.frame")
if (any(df < 0))
stop("non negative value expected in df")
if (is.null(method)) {
cat("1 = BaroniUrbani & Buser\n")
cat("2 = Horn\n")
cat("3 = Yule\n")
cat("Select an integer (13): ")
method < as.integer(readLines(n = 1))
}
df < as.matrix(df)
sites < nrow(df)
species < ncol(df)
sim < array(0, c(as.integer(sites),as.integer(sites)))
spmax <array(0,c(as.integer(species)))
for (x in 1:species) {
spmax[x] < max(df[,x])
}
if (method == 1) {
#compute similarities (BaroniUrbani & Buser)
for (x in 1:sites) {
for (y in 1:sites) {
h1 < 0
h2 < 0
h3 < 0
for (i in 1:species) {
h1 < h1 + min(df[x,i],df[y,i])
h2 < h2 + max(df[x,i],df[y,i])
h3 < h3 + spmax[i]  max(df[x,i],df[y,i])
}
numer < h1 + sqrt(h1*h3)
denom < h2 + sqrt(h1*h3)
sim[x,y] < ifelse(identical(denom,0), 0, numer/denom)
}
}
}
else if (method == 2) {
#compute similarities (Horn)
for (x in 1:sites) {
for (y in 1:sites) {
h1 < 0
h2 < 0
h3 < 0
for (i in 1:species) {
if((df[x,i] + df[y,i]) > 0) h1 < h1 + (df[x,i] + df[y,i]) * log10(df[x,i] + df[y,i])
if(df[x,i] > 0) h2 < h2 + df[x,i] * log10(df[x,i])
if(df[y,i] > 0) h3 < h3 + df[y,i] * log10(df[y,i])
}
x.sum < sum(df[x,])
y.sum < sum(df[y,])
xy.sum < x.sum + y.sum
if (identical(xy.sum, 0)) (sim[x,y] < 0) else (sim[x,y] < (h1  h2  h3)/(xy.sum * log10(xy.sum)x.sum * log10(x.sum)  y.sum * log10(y.sum)))
}
}
}
else if (method == 3) {
#compute similarities (Yule)
for (x in 1:sites) {
for (y in 1:sites) {
h1 < 0
h2 < 0
h3 < 0
h4 < 0
for (i in 1:species) {
h1 < h1 + min(df[x,i], df[y,i])
h2 < h2 + max(df[x,i], df[y,i])  df[y,i]
h3 < h3 + max(df[x,i], df[y,i])  df[x,i]
h4 < h4 + spmax[i]  max(df[x,i], df[y,i])
}
numer < sqrt(h1*h4)
denom < sqrt(h1*h4) + sqrt(h2*h3)
sim[x,y] < ifelse(identical(denom,0), 0, numer/denom)
}
}
}
else stop("Non convenient method")
sim > t(sim)
sim2 < sim[row(sim) > col(sim)]
attr(sim2, "Size") < sites
attr(sim2, "Labels") < dimnames(df)[[1]]
attr(sim2, "Diag") < diag
attr(sim2, "Upper") < upper
attr(sim2, "method") < METHODS[method]
attr(sim2, "call") < match.call()
class(sim2) < "dist"
return(sim2)
}
sim < sim.abund(veg,method=2)As done in the binary case, we will use the attach command:
sim
dis.ho < 1  sim
attach(site)We will start be performing FSO on elevation, which is usally an important variable in the West.
elev.fso < fso(elev, dis.ho)
plot(elev.fso, title="Bryce Canyon", xlab="Actual Elevation", ylab="Apparent Elevation")
elev.fso < fso(elev, dis.ho,permute=1000)The above command uses 1000 permutations and gives us p < 0.001.
slope.fso < fso(slope,dis.ho)
plot(slope.fso, title="Bryce Canyon")
grads.fso < fso(~elev+av+slope+annrad+grorad,dis.ho)Here's the output:
summary(grads.fso)
col variable r pLet's do this with permutations, as the pvalues are likely to be more accurate:
1 1 elev 0.83100659 0.000000e+00
2 4 annrad 0.21870566 5.137353e04
3 5 grorad 0.20833365 3.557737e04
4 3 slope 0.20368768 1.948038e05
5 2 av 0.09118575 2.478808e01
grads.fso < fso(~elev+av+slope+annrad+grorad,dis.ho, permute=1000)Here's the findings using Pearson r values:
summary(grads.fso)
col variable r p
1 1 elev 0.83100659 0.001
2 4 annrad 0.21870566 0.002
3 5 grorad 0.20833365 0.004
4 3 slope 0.20368768 0.002
5 2 av 0.09118575 0.089
col variable r pThese findings are quite similar to those shown by Roberts.
1 1 elev 0.82669241 0.001
2 3 slope 0.33067848 0.001
3 5 grorad 0.27886855 0.001
4 4 annrad 0.27155417 0.001
5 2 av 0.09187828 0.137
grads.mfso < mfso(~elev+slope+grorad,dis.ho,scaling=2)
summary(grads.mfso)
plot(grads.mfso)
variable r p gamma
1 elev 0.83100659 0.001 1.0000000
3 grorad 0.19167651 0.003 0.1620322
2 slope 0.05178301 0.003 0.7454107
variable r p gammaand the Pearson r for the fit between ordination distance and matrix dissimilarity = 0.803.
1 elev 0.8266924 0.001 1.0000000
2 slope 0.2843232 0.001 0.7454107
3 grorad 0.1597620 0.001 0.1620322
st.acr < function(sim, diag=FALSE, upper = FALSE)N.B. If you use dsvdis() in labdsv to calculate similarity/distances matrices, it can do stepacross as part of the function.
{
library(vegan)
dis < 1  sim
#use "shortest" or "extended"
edis < as.matrix(stepacross(dis, path = "shortest", toolong = 1))
sim < 1  edis
amax < max(sim)
amin < min(sim)
sim < (simamin)/(amaxamin)
sim2 < sim[row(sim) > col(sim)]
attr(sim2, "Size") < nrow(sim)
attr(sim2, "Labels") < dimnames(sim)[[1]]
attr(sim2, "Diag") < diag
attr(sim2, "Upper") < upper
attr(sim2, "call") < match.call()
class(sim2) < "dist"
return(sim2)
}
sim.new < st.acr(sim)
dis.ho.new < 1  sim.new
grads.mfso < mfso(~elev+slope+grorad,dis.ho.new,scaling=2,permute=1000)
summary(grads.mfso)
variable r p gamma
1 elev 0.79813451 0.001 1.0000000
3 grorad 0.19636705 0.002 0.1414469
2 slope 0.09942535 0.002 0.8608167
plot(grads.mfso, dis.ho.new)
Boyce, R.L. 1998. Fuzzy set ordination along an elevation gradient on a mountain in Vermont, USA. J. Veg. Sci. 9: 191200.
Boyce, R.L. 2000. Relationships between environmental factors and hemlock distribution at Mt. Ascutney, Vermont. In Proceedings: Symposium on sustainable management of hemlock ecosystems in eastern North America, June 2224, 1999, Durham, NH. General Technical Report NE267. K.A. McManus, K.S. Schields and D. Souto, eds. Newtown Square, PA: U.S. Department of Agriculture, Forest Service, Northeastern Research Station, pp. 113121.
Boyce, R.L, and P.C. Ellison. 2001. Choosing the best
similarity index when performing fuzzy set ordination on binary
data. Journal
of Vegetation Science 12:711720.
Boyce, R.L., R. Clark, and C. Dawson. 2005.
Factors determining alpine species distribution on Goliath Peak, Front
Range, Colorado, U.S.A. Arctic,
Antarctic, and Alpine Research
37:8990.
Bradfield, G.E., and N.C. Kenkel. 1987. Nonlinear ordination using flexible shortest path adjustment of ecological distances. Ecology 68: 750753.
Bragg, D.C. 2002. Fuzzy set classification of oldgrowth southern pine. In Proc. 2001 Southern Mensurationists' Conference, Chattanooga, TN, November 46, 2001. Arkansas Forest Resources Center, Monticello, AR, pp. 3743.
Bray, J.R., and J.T. Curtis. 1957. An ordination of the upland forest communities of southern Wisconsin. Ecol. Monogr. 27: 325349.
Equihua, M. 1991. Fuzzy clustering of ecological data. J. Ecol. 78: 519534.
Equihua, M. 1991. Análisis de la vegetación empleando la teoría de conjuntos difusos como base conceptual. Acta Botanica Mexicana 15: 116.
Fulton, M.R. 1996. An application of fuzzy set ordination to determine tree habitat suitability of sites from a regional data set. J. Veg. Sci. 7: 739746.
Krebs, C.J. 1989. Ecological methodology. Harper & Row, New York.
Legendre, P., and L. Legendre. 1998. Numerical ecology. 2nd English Edn. Elsevier, Amsterdam, 853 p.
Loucks, O.L. 1962. Ordinating forest communities by means of environmental scalars and phytosociological indices. Ecol. Monogr. 32: 137166.
Minieka, E. 1978. Optimization algorithm for networks and graphs.
Marcel Dekker, New York.
Munzbergova, Z., and D. Ward. 2002. Acacia trees as keystone species in
Negev desert ecosystems. J.
Veg. Sci. 13: 227236.
Palmer, M.W. 1994. Fuzzy sets or blurry artifacts? A comment on Zhang and Oxley. J. Veg. Sci. 5: 439440.
Palmer, M.W. 1995. Blurry artifacts: a retraction. J.
Veg. Sci. 6:
447.
Pedersen, T.C., A. BaattrupPedersen, and T.V. Madsen.
2006. Effects of stream restoration and management on plant
communities in lowland streams. Freshwater
Biology 51: 161179.
Pielou, E.C. 1984. The interpretation of ecological data. John Wiley & Sons, New York, USA.
Roberts, D.W. 1986. Ordination on the basis of fuzzy set theory.
Vegetatio
66: 123131.
Roberts, D.W. 1989. Fuzzy systems vegetation
theory. Plant
Ecology 83: 7180.
Roberts, D.W. 2008.
Statistical analysis of multidimensional fuzzy set ordinations.
Ecology
89:12461260.
Rohde, S., M. Schütz, F. Kienast, and P. Englmaier. River
widening: an approach to restoring riparian habitats and plant
species. River
Research and Applications 21: 10751094.
Tamás, J., J. Podani, and P. Csontos. 2001. An extension of
presence/absence coefficients to abundance data: a new look at
absence. Journal
of Vegetation Science 12:401410.
Williamson, M.H. 1978. The ordination of incidence data. J. Ecol. 66: 911920.
Zhang, J.T. 1994. A combination of fuzzy set ordination with detrended correspondence analysis: One way to combine multienvironmental variables with vegetation data. Vegetatio 115: 115121.
Zhang, J.T., and E.R.B. Oxley. 1994. A comparison of three methods
of multivariate analysis of upland grasslands in North Wales. J.
Veg.
Sci. 5: 7176.
Disclaimer and Request: All of these programs are
worksinprogress and probably have some hidden bugs I haven't found
yet. You download and use them at your own risk. I am not responsible
for any injury, real or imagined, that occurs to you if you download or
use them. After all, they are free! All I do ask in return is that you
reference me if you publish any results that use these programs.
Feedback on anything and everything on this page is most welcome.
Revised 26 September 2008