| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 1 | % Generated by roxygen2: do not edit by hand |
| 2 | % Please edit documentation in R/collocationAnalysis.R |
| 3 | \name{collocationAnalysis,KorAPConnection-method} |
| 4 | \alias{collocationAnalysis,KorAPConnection-method} |
| 5 | \alias{collocationAnalysis} |
| 6 | \title{Collocation analysis} |
| 7 | \usage{ |
| 8 | \S4method{collocationAnalysis}{KorAPConnection}( |
| 9 | kco, |
| 10 | node, |
| 11 | vc = "", |
| 12 | lemmatizeNodeQuery = FALSE, |
| 13 | minOccur = 5, |
| 14 | leftContextSize = 5, |
| 15 | rightContextSize = 5, |
| 16 | topCollocatesLimit = 200, |
| 17 | searchHitsSampleLimit = 20000, |
| 18 | ignoreCollocateCase = FALSE, |
| 19 | withinSpan = ifelse(exactFrequencies, "base/s=s", ""), |
| 20 | exactFrequencies = TRUE, |
| Marc Kupietz | 6505ccf | 2021-11-27 17:46:25 +0100 | [diff] [blame] | 21 | stopwords = append(RKorAPClient::synsemanticStopwords(), node), |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 22 | seed = 7, |
| 23 | expand = length(vc) != length(node), |
| Marc Kupietz | 5a336b6 | 2021-11-27 17:51:35 +0100 | [diff] [blame] | 24 | maxRecurse = 0, |
| Marc Kupietz | dadfd91 | 2021-12-22 12:48:20 +0100 | [diff] [blame] | 25 | addExamples = FALSE, |
| Marc Kupietz | 419f21f | 2021-12-07 10:27:30 +0100 | [diff] [blame] | 26 | thresholdScore = "logDice", |
| 27 | threshold = 2, |
| Marc Kupietz | 5a336b6 | 2021-11-27 17:51:35 +0100 | [diff] [blame] | 28 | localStopwords = c(), |
| Marc Kupietz | 47d0d2b | 2021-12-19 16:38:52 +0100 | [diff] [blame] | 29 | collocateFilterRegex = "^[:alnum:]+-?[:alnum:]*$", |
| Marc Kupietz | de679ea | 2025-10-19 13:14:51 +0200 | [diff] [blame] | 30 | queryMissingScores = FALSE, |
| Marc Kupietz | 130a2a2 | 2025-10-18 16:09:23 +0200 | [diff] [blame] | 31 | missingScoreQuantile = 0.05, |
| 32 | vcLabel = NA_character_, |
| Marc Kupietz | db2fabd | 2026-04-27 15:01:37 +0200 | [diff] [blame] | 33 | cacheAs = NULL, |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 34 | ... |
| 35 | ) |
| 36 | } |
| 37 | \arguments{ |
| Marc Kupietz | 617266d | 2025-02-27 10:43:07 +0100 | [diff] [blame] | 38 | \item{kco}{\code{\link[=KorAPConnection]{KorAPConnection()}} object (obtained e.g. from \code{KorAPConnection()}} |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 39 | |
| Marc Kupietz | 209b52c | 2026-06-21 12:14:36 +0200 | [diff] [blame] | 40 | \item{node}{target word or query as a single character string} |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 41 | |
| Marc Kupietz | 209b52c | 2026-06-21 12:14:36 +0200 | [diff] [blame] | 42 | \item{vc}{character vector describing the virtual corpus or corpora in which the query should be performed. An empty string (default) means the whole corpus, as far as it is license-wise accessible.} |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 43 | |
| Marc Kupietz | 67edcb5 | 2021-09-20 21:54:24 +0200 | [diff] [blame] | 44 | \item{lemmatizeNodeQuery}{if TRUE, node query will be lemmatized, i.e. \verb{x -> [tt/l=x]}} |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 45 | |
| 46 | \item{minOccur}{minimum absolute number of observed co-occurrences to consider a collocate candidate} |
| 47 | |
| 48 | \item{leftContextSize}{size of the left context window} |
| 49 | |
| 50 | \item{rightContextSize}{size of the right context window} |
| 51 | |
| 52 | \item{topCollocatesLimit}{limit analysis to the n most frequent collocates in the search hits sample} |
| 53 | |
| 54 | \item{searchHitsSampleLimit}{limit the size of the search hits sample} |
| 55 | |
| 56 | \item{ignoreCollocateCase}{logical, set to TRUE if collocate case should be ignored} |
| 57 | |
| Marc Kupietz | 6bd9cad | 2024-12-18 15:57:26 +0100 | [diff] [blame] | 58 | \item{withinSpan}{KorAP span specification (see \url{https://korap.ids-mannheim.de/doc/ql/poliqarp-plus?embedded=true#spans}) for collocations to be searched within. Defaults to \code{base/s=s}.} |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 59 | |
| 60 | \item{exactFrequencies}{if FALSE, extrapolate observed co-occurrence frequencies from frequencies in search hits sample, otherwise retrieve exact co-occurrence frequencies} |
| 61 | |
| 62 | \item{stopwords}{vector of stopwords not to be considered as collocates} |
| 63 | |
| 64 | \item{seed}{seed for random page collecting order} |
| 65 | |
| 66 | \item{expand}{if TRUE, \code{node} and \code{vc} parameters are expanded to all of their combinations} |
| 67 | |
| Marc Kupietz | 7d400e0 | 2021-12-19 16:39:36 +0100 | [diff] [blame] | 68 | \item{maxRecurse}{apply collocation analysis recursively \code{maxRecurse} times} |
| 69 | |
| 70 | \item{addExamples}{If TRUE, examples for instances of collocations will be added in a column \code{example}. This makes a difference in particular if \code{node} is given as a lemma query.} |
| 71 | |
| Marc Kupietz | db2fabd | 2026-04-27 15:01:37 +0200 | [diff] [blame] | 72 | \item{thresholdScore}{association score function (see \code{\link{association-score-functions}}) to use for computing the threshold that is applied for recursive collocation analysis calls (only applied when \code{maxRecurse > 0})} |
| Marc Kupietz | 7d400e0 | 2021-12-19 16:39:36 +0100 | [diff] [blame] | 73 | |
| Marc Kupietz | db2fabd | 2026-04-27 15:01:37 +0200 | [diff] [blame] | 74 | \item{threshold}{minimum value of \code{thresholdScore} function call to apply collocation analysis recursively (only applied when \code{maxRecurse > 0})} |
| Marc Kupietz | 7d400e0 | 2021-12-19 16:39:36 +0100 | [diff] [blame] | 75 | |
| 76 | \item{localStopwords}{vector of stopwords that will not be considered as collocates in the current function call, but that will not be passed to recursive calls} |
| 77 | |
| Marc Kupietz | 47d0d2b | 2021-12-19 16:38:52 +0100 | [diff] [blame] | 78 | \item{collocateFilterRegex}{allow only collocates matching the regular expression} |
| 79 | |
| Marc Kupietz | de679ea | 2025-10-19 13:14:51 +0200 | [diff] [blame] | 80 | \item{queryMissingScores}{if TRUE, attempt to retrieve corpus-based association scores for vc/collocate combinations that would otherwise be imputed, by re-querying the KorAP backend without applying the collocate frequency threshold} |
| 81 | |
| Marc Kupietz | 9525334 | 2026-08-31 10:18:43 +0200 | [diff] [blame] | 82 | \item{missingScoreQuantile}{lower quantile (evaluated per association measure over the pooled result set) that anchors the adaptive floor used for imputing missing scores between virtual corpora; a robust spread is subtracted from this anchor so the imputed values stay at or below the weakest observed scores. Imputed cells are marked in the \verb{imputed*} columns; see the section on interpreting multi-VC comparisons below} |
| Marc Kupietz | 130a2a2 | 2025-10-18 16:09:23 +0200 | [diff] [blame] | 83 | |
| 84 | \item{vcLabel}{optional label override for the current virtual corpus (used internally when named VC collections are expanded)} |
| 85 | |
| Marc Kupietz | 37f9607 | 2026-09-03 07:18:11 +0200 | [diff] [blame] | 86 | \item{cacheAs}{path to an RDS file for caching the result. If the file already exists, the cached result is loaded and returned immediately without contacting the server. Otherwise the analysis is run normally and the result is saved to the file before returning. Defaults to \code{NULL} (no caching). |
| 87 | |
| 88 | The analysis parameters are stored alongside the result. If they differ from |
| 89 | those of the current call, the cached result would not be the one that was |
| 90 | asked for, so it is recomputed and the file overwritten, with a warning |
| 91 | naming the parameters that differ. Pass a different \code{cacheAs} file name |
| 92 | to keep an existing analysis. Cache files written by RKorAPClient 1.3.0 do |
| 93 | not contain the parameters yet and are used as they are.} |
| Marc Kupietz | db2fabd | 2026-04-27 15:01:37 +0200 | [diff] [blame] | 94 | |
| Marc Kupietz | 67edcb5 | 2021-09-20 21:54:24 +0200 | [diff] [blame] | 95 | \item{...}{more arguments will be passed to \code{\link[=collocationScoreQuery]{collocationScoreQuery()}}} |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 96 | } |
| 97 | \value{ |
| Marc Kupietz | 130a2a2 | 2025-10-18 16:09:23 +0200 | [diff] [blame] | 98 | A tibble where each row represents a candidate collocate for the requested node. |
| 99 | Columns include (depending on the selected association measures): |
| 100 | |
| 101 | \itemize{ |
| 102 | \item \code{node}, \code{collocate}, \code{vc}, \code{label}: identifiers for the query node, collocate, virtual corpus, and optional label. |
| 103 | \item Frequency and contingency information such as \code{frequency}, \code{O}, \code{O1}, \code{O2}, \code{E}, \code{leftContextSize}, \code{rightContextSize}, and \code{w}. |
| 104 | \item Association measures (e.g. \code{logDice}, \code{ll}, \code{mi}, ...), one column per requested scorer. |
| 105 | \item Per-labelled association scores produced by multi-VC comparisons using the pattern \code{<measure>_<label>}. |
| 106 | \item Ranks per label/measure with the pattern \code{rank_<label>_<measure>} (1 is best) and the corresponding percentile ranks \code{percentile_rank_<label>_<measure>}. |
| 107 | \item Pairwise contrasts for two-label comparisons, e.g. \code{delta_<measure>}, \code{delta_rank_<measure>}, and \code{delta_percentile_rank_<measure>}. |
| Marc Kupietz | 09b1c08 | 2026-05-01 14:45:47 +0200 | [diff] [blame] | 108 | \item Summary columns describing the strongest labels per measure (\code{winner_*}, \code{runner_up_*}, \code{loser_*}, and \code{max_delta_*}), including winner/loser \code{webUIRequestUrl} columns. In multi-VC comparisons, missing per-label concordance URLs are derived from another available row URL for the same \code{node}/\code{collocate} by replacing the \code{cq} parameter with the target label's virtual corpus. Unsuffixed \code{winner_webUIRequestUrl} and \code{loser_webUIRequestUrl} columns are populated only when the score-based URL choices agree. |
| Marc Kupietz | d7bb5cb | 2026-08-31 10:18:02 +0200 | [diff] [blame] | 109 | \item \code{imputed_<label>}, \code{n_imputed}, and \code{imputed}: flags marking rows whose scores were not observed for some label but imputed (see \code{missingScoreQuantile}). Filter with \code{dplyr::filter(!imputed)} to keep only collocates attested in every compared virtual corpus. |
| Marc Kupietz | 130a2a2 | 2025-10-18 16:09:23 +0200 | [diff] [blame] | 110 | \item Optional helper columns such as \code{query}, \code{example}, or \code{url} when example retrieval is requested. |
| 111 | } |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 112 | } |
| 113 | \description{ |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 114 | Performs a collocation analysis for the given node (or query) |
| 115 | in the given virtual corpus. |
| 116 | } |
| 117 | \details{ |
| 118 | The collocation analysis is currently implemented on the client side, as some of the |
| 119 | functionality is not yet provided by the KorAP backend. Mainly for this reason |
| 120 | it is very slow (several minutes, up to hours), but on the other hand very flexible. |
| 121 | You can, for example, perform the analysis in arbitrary virtual corpora, use complex node queries, |
| 122 | and look for expression-internal collocates using the focus function (see examples and demo). |
| 123 | |
| 124 | To increase speed at the cost of accuracy and possible false negatives, |
| 125 | you can decrease searchHitsSampleLimit and/or topCollocatesLimit and/or set exactFrequencies to FALSE. |
| 126 | |
| Marc Kupietz | e7f0d68 | 2025-02-19 10:50:59 +0100 | [diff] [blame] | 127 | Note that some outdated non-DeReKo back-ends might not yet support returning tokenized matches (warning issued). |
| 128 | In this case, the client library will fall back to client-side tokenization which might be slightly less accurate. |
| 129 | This might lead to false negatives and to frequencies that differ from corresponding ones acquired via the web |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 130 | user interface. |
| 131 | } |
| Marc Kupietz | 9525334 | 2026-08-31 10:18:43 +0200 | [diff] [blame] | 132 | \section{Interpreting multi-VC comparisons}{ |
| 133 | |
| 134 | |
| Marc Kupietz | ba15cff | 2026-08-31 10:19:56 +0200 | [diff] [blame] | 135 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}} |
| 136 | |
| 137 | The comparison columns produced when \code{vc} holds more than one virtual corpus |
| 138 | are experimental: their names and semantics may still change in a future |
| 139 | release without a deprecation cycle. Code that has to keep working across |
| 140 | versions should select the columns it needs explicitly. |
| 141 | |
| 142 | They are an exploration aid, not a significance test. When reading them, keep |
| 143 | three properties in mind. |
| Marc Kupietz | 9525334 | 2026-08-31 10:18:43 +0200 | [diff] [blame] | 144 | |
| 145 | \strong{Imputed scores describe presence/absence, not contrast.} A collocate |
| 146 | that passes the \code{minOccur} and \code{topCollocatesLimit} thresholds in one virtual |
| 147 | corpus but not in another has no observed score for the latter. Such cells are |
| 148 | imputed from a floor derived from the pooled result set (see |
| 149 | \code{missingScoreQuantile}), so the corresponding \verb{delta_*} and \verb{max_delta_*} |
| 150 | values measure the distance to that floor rather than an attested difference. |
| 151 | The \code{imputed}, \code{n_imputed} and \verb{imputed_<label>} columns mark these rows; |
| 152 | \code{dplyr::filter(!imputed)} restricts the result to collocates attested |
| 153 | everywhere, and \code{queryMissingScores = TRUE} replaces most imputed cells with |
| 154 | scores actually retrieved from the backend. |
| 155 | |
| 156 | \strong{Imputed values are relative to one analysis.} The floor is computed |
| 157 | from the scores present in the result at hand. Analysing a node on its own and |
| 158 | analysing it together with other nodes therefore yield different imputed |
| 159 | values, and deltas involving imputed cells are not comparable across separate |
| 160 | calls. Deltas between observed scores are unaffected. |
| 161 | |
| 162 | \strong{Winners carry no uncertainty.} Unlike \code{\link[=ci]{ci()}}, which attaches |
| 163 | confidence intervals to relative frequencies, the \verb{winner_*} / \verb{loser_*} |
| 164 | columns simply order point estimates. A collocate wins by a hair on six |
| 165 | occurrences exactly as decisively as one that wins by a wide margin on |
| 166 | thousands. Consult the observed frequencies (\code{O}, \code{O1}, \code{O2}) and the |
| 167 | \code{webUIRequestUrl} concordance links before drawing conclusions from a |
| 168 | small difference. |
| 169 | |
| 170 | Note also that \verb{rank_<label>_<measure>} and |
| 171 | \verb{percentile_rank_<label>_<measure>} are computed within each label, over that |
| 172 | label's own candidate set. Candidate sets usually differ in size between |
| 173 | virtual corpora, so rank-based deltas compare positions in populations of |
| 174 | different sizes. |
| 175 | } |
| 176 | |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 177 | \examples{ |
| Marc Kupietz | 6ae7605 | 2021-09-21 10:34:00 +0200 | [diff] [blame] | 178 | \dontrun{ |
| 179 | |
| Marc Kupietz | b1dec01 | 2025-06-04 17:16:57 +0200 | [diff] [blame] | 180 | # Find top collocates of "Packung" inside and outside the sports domain. |
| 181 | KorAPConnection(verbose = TRUE) |> |
| 182 | collocationAnalysis("Packung", |
| 183 | vc = c("textClass=sport", "textClass!=sport"), |
| 184 | leftContextSize = 1, rightContextSize = 1, topCollocatesLimit = 20 |
| 185 | ) |> |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 186 | dplyr::filter(logDice >= 5) |
| 187 | } |
| 188 | |
| Marc Kupietz | 6ae7605 | 2021-09-21 10:34:00 +0200 | [diff] [blame] | 189 | \dontrun{ |
| 190 | |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 191 | # Identify the most prominent light verb construction with "in ... setzen". |
| 192 | # Note that, currently, the use of focus function disallows exactFrequencies. |
| Marc Kupietz | 463bb16 | 2025-03-26 10:23:33 +0100 | [diff] [blame] | 193 | KorAPConnection(verbose = TRUE) |> |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 194 | collocationAnalysis("focus(in [tt/p=NN] {[tt/l=setzen]})", |
| Marc Kupietz | b1dec01 | 2025-06-04 17:16:57 +0200 | [diff] [blame] | 195 | leftContextSize = 1, rightContextSize = 0, exactFrequencies = FALSE, topCollocatesLimit = 20 |
| 196 | ) |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 197 | } |
| 198 | |
| 199 | } |
| 200 | \seealso{ |
| Marc Kupietz | 209b52c | 2026-06-21 12:14:36 +0200 | [diff] [blame] | 201 | Other collocation analysis functions: |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 202 | \code{\link{association-score-functions}}, |
| 203 | \code{\link{collocationScoreQuery,KorAPConnection-method}}, |
| Marc Kupietz | 209b52c | 2026-06-21 12:14:36 +0200 | [diff] [blame] | 204 | \code{\link[=synsemanticStopwords]{synsemanticStopwords()}} |
| Marc Kupietz | dbd431a | 2021-08-29 12:17:45 +0200 | [diff] [blame] | 205 | } |
| 206 | \concept{collocation analysis functions} |