189189# '
190190# ' @rdname dna_multiclust
191191# ' @importFrom stats as.dist cor hclust cutree kmeans
192+ # ' @importFrom utils packageVersion
192193# ' @export
193194dna_multiclust <- function (statementType = " DNA Statement" ,
194195 variable1 = " organization" ,
@@ -233,7 +234,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
233234 infomap = TRUE ,
234235 label_prop = TRUE ,
235236 spinglass = FALSE ) {
236-
237+
237238 # check dependencies
238239 if (! requireNamespace(" igraph" , quietly = TRUE )) { # version 0.8.1 required for edge betweenness to work fine.
239240 stop(" The 'dna_multiclust' function requires the 'igraph' package to be installed.\n " ,
@@ -249,7 +250,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
249250 equivalence <- FALSE
250251 warning(" Argument 'equivalence = TRUE' requires the 'sna' package, which is not installed.\n Setting 'equivalence = FALSE'. Consider installing the 'sna' package." )
251252 }
252-
253+
253254 # check argument validity
254255 if (is.null(k ) || is.na(k ) || ! is.numeric(k ) || length(k ) > 1 || is.infinite(k ) || k < 0 ) {
255256 stop(" 'k' must be a non-negative integer number. Can be 0 for flexible numbers of clusters." )
@@ -261,7 +262,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
261262 k <- 0
262263 warning(" 'k' must be 0 (for arbitrary numbers of clusters) or larger than 1 (to constrain number of clusters). Using 'k = 0'." )
263264 }
264-
265+
265266 # determine what kind of two-mode network to create
266267 if (is.null(qualifier ) || is.na(qualifier ) || ! is.character(qualifier )) {
267268 qualifierAggregation <- " ignore"
@@ -273,7 +274,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
273274 qualifierAggregation <- " subtract"
274275 }
275276 }
276-
277+
277278 nw_aff <- dna_network(networkType = " twomode" ,
278279 statementType = statementType ,
279280 variable1 = variable1 ,
@@ -326,7 +327,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
326327 invertSources = invertSources ,
327328 invertSections = invertSections ,
328329 invertTypes = invertTypes )
329-
330+
330331 if (timeWindow == " no" ) {
331332 dta <- list ()
332333 dta $ networks <- list (nw_sub )
@@ -335,7 +336,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
335336 dta $ networks <- list (nw_aff )
336337 nw_aff <- dta
337338 }
338-
339+
339340 obj <- list ()
340341 if (isTRUE(saveObjects )) {
341342 obj $ cl <- list ()
@@ -350,7 +351,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
350351 num_networks <- 1
351352 }
352353 for (i in 1 : num_networks ) {
353-
354+
354355 # prepare dates
355356 if (timeWindow == " no" ) {
356357 dta_dat [[i ]] <- data.frame (i = i ,
@@ -362,7 +363,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
362363 middle.date = attributes(nw_sub [[i ]])$ middle ,
363364 stop.date = attributes(nw_sub [[i ]])$ stop )
364365 }
365-
366+
366367 # prepare two-mode network
367368 if (" dna_network_onemode_timewindows" %in% class(nw_sub )) {
368369 x <- nw_aff [[i ]]
@@ -377,7 +378,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
377378 }
378379 combined <- combined [rowSums(combined ) > 0 , , drop = FALSE ]
379380 rn <- rownames(combined )
380-
381+
381382 # Jaccard distances for two-mode network (could be done using vegdist function in vegan package, but saving the dependency)
382383 combined <- matrix (as.integer(combined > 0 ), nrow = nrow(combined )) # probably not necessary, but ensure it's an integer matrix
383384 intersections <- tcrossprod(combined ) # compute intersections using cross-product
@@ -388,7 +389,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
388389 jaccard_distances <- 1 - jaccard_similarities # convert to Jaccard distances
389390 rownames(jaccard_distances ) <- rn # re-attach the row names
390391 jac <- stats :: as.dist(jaccard_distances ) # convert to dist object
391-
392+
392393 # prepare one-mode network
393394 if (" dna_network_onemode_timewindows" %in% class(nw_sub )) {
394395 y <- nw_sub [[i ]]
@@ -398,12 +399,12 @@ dna_multiclust <- function(statementType = "DNA Statement",
398399 y [y < 0 ] <- 0
399400 class(y ) <- " matrix"
400401 g <- igraph :: graph_from_adjacency_matrix(y , mode = " undirected" , weighted = TRUE )
401-
402+
402403 if (nrow(combined ) > 1 ) {
403404 counter_current <- 1
404405 current_cl <- list ()
405406 current_mod <- numeric ()
406-
407+
407408 # Hierarchical clustering with single linkage
408409 if (isTRUE(single ) && k > 1 ) {
409410 try({
@@ -427,7 +428,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
427428 counter <- counter + 1
428429 }, silent = TRUE )
429430 }
430-
431+
431432 # Hierarchical clustering with single linkage with optimal k
432433 if (isTRUE(single ) && k < 2 ) {
433434 try({
@@ -459,7 +460,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
459460 counter <- counter + 1
460461 }, silent = TRUE )
461462 }
462-
463+
463464 # Hierarchical clustering with average linkage
464465 if (isTRUE(average ) && k > 1 ) {
465466 try({
@@ -483,7 +484,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
483484 counter <- counter + 1
484485 }, silent = TRUE )
485486 }
486-
487+
487488 # Hierarchical clustering with average linkage with optimal k
488489 if (isTRUE(average ) && k < 2 ) {
489490 try({
@@ -515,7 +516,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
515516 counter <- counter + 1
516517 }, silent = TRUE )
517518 }
518-
519+
519520 # Hierarchical clustering with complete linkage
520521 if (isTRUE(complete ) && k > 1 ) {
521522 try({
@@ -539,7 +540,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
539540 counter <- counter + 1
540541 }, silent = TRUE )
541542 }
542-
543+
543544 # Hierarchical clustering with complete linkage with optimal k
544545 if (isTRUE(complete ) && k < 2 ) {
545546 try({
@@ -571,7 +572,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
571572 counter <- counter + 1
572573 }, silent = TRUE )
573574 }
574-
575+
575576 # Hierarchical clustering with the Ward algorithm
576577 if (isTRUE(ward ) && k > 1 ) {
577578 try({
@@ -595,7 +596,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
595596 counter <- counter + 1
596597 }, silent = TRUE )
597598 }
598-
599+
599600 # Hierarchical clustering with the Ward algorithm with optimal k
600601 if (isTRUE(ward ) && k < 2 ) {
601602 try({
@@ -627,7 +628,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
627628 counter <- counter + 1
628629 }, silent = TRUE )
629630 }
630-
631+
631632 # k-means
632633 if (isTRUE(kmeans ) && k > 1 ) {
633634 try({
@@ -651,7 +652,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
651652 counter <- counter + 1
652653 }, silent = TRUE )
653654 }
654-
655+
655656 # k-means with optimal k
656657 if (isTRUE(kmeans ) && k < 2 ) {
657658 try({
@@ -684,7 +685,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
684685 counter <- counter + 1
685686 }, silent = TRUE )
686687 }
687-
688+
688689 # pam
689690 if (isTRUE(pam ) && k > 1 ) {
690691 try({
@@ -708,7 +709,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
708709 counter <- counter + 1
709710 }, silent = TRUE )
710711 }
711-
712+
712713 # pam with optimal k
713714 if (isTRUE(pam ) && k < 2 ) {
714715 try({
@@ -741,7 +742,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
741742 counter <- counter + 1
742743 }, silent = TRUE )
743744 }
744-
745+
745746 # Equivalence clustering
746747 if (isTRUE(equivalence ) && k > 1 ) {
747748 try({
@@ -765,7 +766,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
765766 counter <- counter + 1
766767 }, silent = TRUE )
767768 }
768-
769+
769770 # Equivalence clustering with optimal k
770771 if (isTRUE(equivalence ) && k < 2 ) {
771772 try({
@@ -797,7 +798,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
797798 counter <- counter + 1
798799 }, silent = TRUE )
799800 }
800-
801+
801802 # CONCOR based on the positive subtract network
802803 if (isTRUE(concor_one ) && k %in% c(0 , 2 )) {
803804 try({
@@ -827,7 +828,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
827828 counter <- counter + 1
828829 }, silent = TRUE )
829830 }
830-
831+
831832 # CONCOR based on the combined affiliation network
832833 if (isTRUE(concor_two ) && k %in% c(0 , 2 )) {
833834 try({
@@ -857,7 +858,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
857858 counter <- counter + 1
858859 }, silent = TRUE )
859860 }
860-
861+
861862 # Louvain clustering
862863 if (isTRUE(louvain ) && k < 2 ) {
863864 try({
@@ -881,7 +882,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
881882 counter <- counter + 1
882883 }, silent = TRUE )
883884 }
884-
885+
885886 # Fast & Greedy community detection (with or without cut)
886887 if (isTRUE(fastgreedy )) {
887888 try({
@@ -912,7 +913,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
912913 counter <- counter + 1
913914 }, silent = TRUE )
914915 }
915-
916+
916917 # Walktrap community detection (with or without cut)
917918 if (isTRUE(walktrap )) {
918919 try({
@@ -943,7 +944,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
943944 counter <- counter + 1
944945 }, silent = TRUE )
945946 }
946-
947+
947948 # Leading Eigenvector community detection (only without cut)
948949 if (isTRUE(leading_eigen ) && k < 2 ) { # it *should* work with cut_at because is.hierarchical(cl) returns TRUE, but it never works...
949950 try({
@@ -967,7 +968,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
967968 counter <- counter + 1
968969 }, silent = TRUE )
969970 }
970-
971+
971972 # Edge Betweenness community detection (with or without cut)
972973 if (isTRUE(edge_betweenness )) {
973974 try({
@@ -998,7 +999,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
998999 counter <- counter + 1
9991000 }, silent = TRUE )
10001001 }
1001-
1002+
10021003 # Infomap community detection
10031004 if (isTRUE(infomap ) && k < 2 ) {
10041005 try({
@@ -1022,7 +1023,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
10221023 counter <- counter + 1
10231024 }, silent = TRUE )
10241025 }
1025-
1026+
10261027 # Label Propagation community detection
10271028 if (isTRUE(label_prop ) && k < 2 ) {
10281029 try({
@@ -1046,7 +1047,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
10461047 counter <- counter + 1
10471048 }, silent = TRUE )
10481049 }
1049-
1050+
10501051 # Spinglass community detection
10511052 if (isTRUE(spinglass ) && k < 2 ) {
10521053 try({
@@ -1070,7 +1071,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
10701071 counter <- counter + 1
10711072 }, silent = TRUE )
10721073 }
1073-
1074+
10741075 # retain cluster object where modularity was maximal
10751076 if (isTRUE(saveObjects ) && length(current_cl ) > 0 ) {
10761077 obj $ cl [[i ]] <- current_cl [[which.max(current_mod )]]
@@ -1094,7 +1095,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
10941095 function (x ) obj $ modularity $ method [obj $ modularity $ i == x & obj $ modularity $ modularity == max(obj $ modularity $ modularity [obj $ modularity $ i == x ], na.rm = TRUE )][1 ])
10951096 # attach k to max_mod
10961097 obj $ max_mod $ k <- sapply(obj $ max_mod $ i , function (x ) max(obj $ modularity $ k [obj $ modularity $ i == x ], na.rm = TRUE ))
1097-
1098+
10981099 # diagnostics
10991100 if (isTRUE(single ) && ! " Hierarchical (Single)" %in% obj $ modularity $ method && k > 1 ) {
11001101 warning(" 'single' omitted due to an unknown problem." )
@@ -1147,7 +1148,7 @@ dna_multiclust <- function(statementType = "DNA Statement",
11471148 if (isTRUE(spinglass ) && ! " Spinglass" %in% obj $ modularity $ method && k < 2 ) {
11481149 warning(" 'spinglass' omitted due to an unknown problem." )
11491150 }
1150-
1151+
11511152 class(obj ) <- " dna_multiclust"
11521153 return (obj )
11531154}
0 commit comments