File: intersectDiagram.R

package info (click to toggle)
r-cran-plotrix 3.8-4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,588 kB
  • sloc: makefile: 6
file content (138 lines) | stat: -rwxr-xr-x 5,731 bytes parent folder | download | duplicates (3)
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
intersectDiagram<-function(x,pct=FALSE,show.nulls=FALSE,xnames=NULL, 
 sep="+",mar=c(0,0,3,0),main="Intersection Diagram",cex=1,col=NULL,
 minspacing=NA,all.intersections=FALSE,include=NULL,
 null.label="Non-set") {

 matchParts<-function(x,table,ignore.case=TRUE) {
  for(pattern in 1:length(x)) {
   match_index<-grep(x[pattern],table,ignore.case=ignore.case)
   if(length(match_index)) return(match_index)
  }
  return(0)
 }
 if(!inherits(x,"intersectList")) {
  if(is.matrix(x) || is.data.frame(x)) {
   if(is.data.frame(x)) 
    x<-as.matrix(x)
    x<-makeIntersectList(x,xnames=xnames,sep=sep)
  }
  if(!inherits(x,"intersectList")) 
   stop("x must be a matrix, data frame or intersectList")
 }
 oldmar<-par("mar")
 par(mar=mar)
 # attribute labels
 attributes<-x[[length(x)]]
 # get all the names for the individual attributes
 if(is.null(include)) include<-attributes
 # total number of attributes
 nattributes<-length(attributes)
 # peel off the number of objects and the attributes for display
 x[[length(x)]]<-NULL
 nobjects<-x[[length(x)]]
 x[[length(x)]]<-NULL
 # number of intersection levels with at least one object
 nlevels<-length(x)
 # if no colors specified, use rainbow
 if(is.null(col)) col<-c(rainbow(nattributes),NA)
 else
  if(length(col) < nattributes) col<-rep(col,length.out=nattributes)
 # total number of objects for each intersection level
 objectsums<-sapply(x,sum)
 # index of level with the most objects
 maxlevel<-which.max(objectsums)
 nNonZero<-function(x) return(sum(x > 0))
 # number of intersections with at least one member for each
 # intersection level or all intersections if the somewhat dangerous
 # "show everything" option is TRUE
 if(all.intersections) nintersects<-sapply(x,length)
 else nintersects<-sapply(x,nNonZero)
 # maximum number of intersections in a given level
 maxintersections<-max(nintersects)
 # largest intersection set in x
 maxn<-max(unlist(x))
 # default to a minimum spacing of one tenth of the largest intersection set
 if(is.na(minspacing)) minspacing<-0.1 * maxn
 # x limit that will hold the maximum number of objects and allow
 # spacing for the maximum number of intersections in units of objects 
 maxx<-ifelse(nobjects > objectsums[maxlevel],
  nobjects,objectsums[maxlevel] + minspacing * maxintersections)
 # have to escape the separator in case it is "+" (default) or
 # some other character that means something to some function
 attsep<-paste("[",sep,"]",sep="")
 # display the empty plot
 plot(0,xlim=c(0,maxx),ylim=c(0,nlevels+show.nulls), 
  main=main,xlab="",ylab="",type="n",axes=FALSE)
 # step through each level of intersections
 for(level in 1:nlevels) {
  # determine the intersect level by the number of elements in the first name
  intersectLevel<-length(unlist(strsplit(names(x[[level]][1]),attsep)))
  # indices of intersections with at least one object in this level
  # or just all of the intersections
  if(all.intersections) intersections<-1:nintersects[[level]]
  else intersections<-which(x[[level]] > 0)
  # get all the names in this level with at least one object
  blocknames<-names(x[[level]])[intersections]
  # spacing between intersection sets in object units
  spacing<-(maxx - objectsums[level])/nintersects[level]
  # left edges of the rectangles in x positions
  leftx<-c(0,cumsum(x[[level]][intersections] + spacing)) + spacing/2
  # now step through the intersections in this level
  for(intersect in 1:length(intersections)) {
   # check if this intersection is to be displayed
   if(matchParts(include,blocknames[intersect])) {
    # make the label for the intersection
    cellqnt<-ifelse(pct,
     paste(round(100*x[[level]][intersections[intersect]]/nobjects,1),
     "%",sep=""),x[[level]][intersections[intersect]])
    # indices of the colors to use for this rectangle
    colindex<-
     which(attributes %in% unlist(strsplit(blocknames[intersect],attsep)))
    # number of colors
    ncol<-length(colindex)
    # width of each color slice
    xinc<-x[[level]][intersections[intersect]]/ncol
    # colors for the slices
    slicecol<-col[colindex]
    # start at the left edge of the sliced rectangle
    offset<-0
    # step through the slices
    for(slice in 1:ncol) {
     # first draw the rectangle with no border
     rect(leftx[intersect]+offset,nlevels-level+show.nulls+0.1,
      leftx[intersect]+offset+xinc,nlevels-level+show.nulls+0.9,
      col=slicecol[slice],border=NA)
     # move to the left edge of the next slice
     offset<-offset+xinc
    }
    # draw a box around the sliced rectangle
    rect(leftx[intersect],nlevels-level+show.nulls+0.1,
     leftx[intersect]+x[[level]][intersections[intersect]], 
     nlevels-level+show.nulls+0.9)
    # display the label for this rectangle
    boxed.labels(leftx[intersect]+x[[level]][intersections[intersect]]/2, 
     nlevels-level+show.nulls+0.5,
     paste(blocknames[intersect],cellqnt,sep="\n"),cex=cex)
   }
  }
 }
 if(show.nulls) {
  # number of objects with no set membership or no attributes
  nonset<-as.numeric(nobjects - sum(objectsums))
  # left edge of the rectangle
  leftnulls<-sum(par("usr")[1:2])/2-nonset/2
  # draw the rectangle
  if(nonset) rect(leftnulls,0.1,leftnulls+nonset,0.9)
  # center of the rectangle
  xpos<-leftnulls+nonset/2
  # display the label
  if(pct) nonset<-paste(round(100*nonset/nobjects,1),"%",sep="")
  boxed.labels(xpos,0.5,paste(null.label,nonset,sep="\n"),cex=cex)
 }
 # restore the original plot parameters
 par(mar=oldmar)
 # stick the number of objects and attributes back on
 x[[length(x) + 1]]<-nobjects
 x[[length(x) + 1]]<-attributes
 invisible(x)
}