Skip to content

Circular Data Base

Circular

Circular Data Analysis Object.

This class encapsulates circular data and provides tools for descriptive statistics, hypothesis testing, and visualization. It automatically computes key circular statistics and tests when the data are loaded.

Parameters:

Name Type Description Default
data array - like(n)

The raw circular data, typically in degrees, radians, or other angular units.

required
w array - like(n) or None

Frequencies or weights for the data points. If None, all data points are treated equally. Default is None.

None
bins (int, array - like(n + 1) or None)

Number of bins or bin edges to group the data. If None, the data is not binned. Default is None.

None
unit str

Unit of the input data. Must be one of {"degree", "radian", "hour"}. Default is "degree".

'degree'
n_intervals int, float, or None

Number of intervals in a full cycle. If None, the value is inferred based on the unit:

  • 360 for degrees,
  • \(2\pi\) for radians,
  • 24 for hours.

Custom intervals require explicit input. Default is None.

None
n_clusters_max int

Maximum number of clusters to test for a mixture of von Mises distributions. Default is 1.

1
kwargs dict

Additional keyword arguments to customize the computation of statistics such as the median.

{}

Attributes:

Name Type Description
n int

Total sample size, including weights.

mean float

Angular mean in radians.

mean_ci tuple of float

Confidence interval for the angular mean, if applicable.

median float

Angular median in radians.

median_ci tuple of float

Confidence interval for the angular median, if computed.

r float

Resultant vector length, measuring data concentration (0 to 1).

kappa float

Concentration parameter, measuring data sharpness.

s float

Angular deviation, measuring data dispersion.

skewness float

Circular skewness of the data.

kurtosis float

Circular kurtosis of the data.

R float

Rayleigh's R statistic, derived from the resultant vector length.

mixtures list

Mixture models of von Mises distributions fitted to the data (if n_clusters_max > 1).

Methods:

Name Description
summary

Returns a detailed summary of the computed statistics.

plot

Visualizes the circular data, including histograms and other representations.

Notes
  • Angular data is automatically converted to radians for internal computations.
  • Data can be grouped or ungrouped. Ungrouped data is handled by assigning equal weights.
  • The Rayleigh test for angular mean is computed, with p-values indicating significance.
  • Confidence intervals for the angular mean are approximated using either bootstrap or dispersion methods, depending on the sample size and significance.
References
  • Zar, J. H. (2010). Biostatistical Analysis (5th Edition). Pearson.
  • Fisher, N. I. (1995). Statistical Analysis of Circular Data. Cambridge University Press.

Examples:

Basic Usage
data = [30, 60, 90, 120, 150]
circ = Circular(data, unit="degree")
print(circ.summary())
Grouped Data
data = [0, 30, 60, 90]
weights = [1, 2, 3, 4]
circ = Circular(data, w=weights, unit="degree")
print(circ.summary())
Source code in pycircstat2/base.py
 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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
class Circular:
    r"""
    Circular Data Analysis Object.

    This class encapsulates circular data and provides tools for descriptive statistics,
    hypothesis testing, and visualization. It automatically computes key circular
    statistics and tests when the data are loaded.

    Parameters
    ----------
    data : array-like (n,)
        The raw circular data, typically in degrees, radians, or other angular units.

    w : array-like (n,) or None, optional
        Frequencies or weights for the data points. If None, all data points are treated equally.
        Default is None.

    bins : int, array-like (n+1,) or None, optional
        Number of bins or bin edges to group the data. If None, the data is not binned.
        Default is None.

    unit : str, optional
        Unit of the input data. Must be one of {"degree", "radian", "hour"}.
        Default is "degree".

    n_intervals : int, float, or None, optional
        Number of intervals in a full cycle. If None, the value is inferred based on the unit:

        - 360 for degrees,
        - $2\pi$ for radians,
        - 24 for hours.

        Custom intervals require explicit input.
        Default is None.

    n_clusters_max : int, optional
        Maximum number of clusters to test for a mixture of von Mises distributions.
        Default is 1.

    kwargs : dict, optional
        Additional keyword arguments to customize the computation of statistics such as the median.

    Attributes
    ----------
    n : int
        Total sample size, including weights.

    mean : float
        Angular mean in radians.

    mean_ci : tuple of float
        Confidence interval for the angular mean, if applicable.

    median : float
        Angular median in radians.

    median_ci : tuple of float
        Confidence interval for the angular median, if computed.

    r : float
        Resultant vector length, measuring data concentration (0 to 1).

    kappa : float
        Concentration parameter, measuring data sharpness.

    s : float
        Angular deviation, measuring data dispersion.

    skewness : float
        Circular skewness of the data.

    kurtosis : float
        Circular kurtosis of the data.

    R : float
        Rayleigh's R statistic, derived from the resultant vector length.

    mixtures : list
        Mixture models of von Mises distributions fitted to the data (if `n_clusters_max > 1`).

    Methods
    -------
    summary()
        Returns a detailed summary of the computed statistics.

    plot(ax=None, kind=None, **kwargs)
        Visualizes the circular data, including histograms and other representations.

    Notes
    -----
    - Angular data is automatically converted to radians for internal computations.
    - Data can be grouped or ungrouped. Ungrouped data is handled by assigning equal weights.
    - The Rayleigh test for angular mean is computed, with p-values indicating significance.
    - Confidence intervals for the angular mean are approximated using either bootstrap
      or dispersion methods, depending on the sample size and significance.

    References
    ----------
    - Zar, J. H. (2010). Biostatistical Analysis (5th Edition). Pearson.
    - Fisher, N. I. (1995). Statistical Analysis of Circular Data. Cambridge University Press.

    Examples
    --------

    #### Basic Usage

    ```python
    data = [30, 60, 90, 120, 150]
    circ = Circular(data, unit="degree")
    print(circ.summary())
    ```

    #### Grouped Data

    ```python
    data = [0, 30, 60, 90]
    weights = [1, 2, 3, 4]
    circ = Circular(data, w=weights, unit="degree")
    print(circ.summary())
    ```
    """

    def __init__(
        self,
        data: Union[np.ndarray, list],  # angle
        w: Optional[Union[np.ndarray, list]] = None,  # frequency
        bins: Optional[Union[int, np.ndarray]] = None,
        unit: str = "degree",
        n_intervals: Optional[Union[
            int, float
        ]] = None,  # number of intervals in the full cycle
        n_clusters_max: int = 1,  # number of clusters to be tested for mixture of von Mises
        rotate: Optional[float] = None, # in rad
        **kwargs,
    ):
        # meta
        self.unit = unit
        if n_intervals is None:
            if unit == "degree":
                self.n_intervals = n_intervals = 360
            elif unit == "radian":
                self.n_intervals = n_intervals = 2 * np.pi
            elif unit == "hour":
                self.n_intervals = n_intervals = 24
            else:
                raise ValueError(
                    "You need to provide a value for `n_intervals` if it is not `degree`, `radian` or hour."
                )
        else:
            self.n_intervals = n_intervals

        self.n_clusters_max = n_clusters_max
        self.kwargs_median = kwargs_median = {
            **{
                "method": "deviation",
                "return_average": True,
                "average_method": "all",
            },
            **kwargs.pop("kwargs_median", {}),
        }
        self.kwargs_mean_ci = kwargs_mean_ci = kwargs.pop("kwargs_mean_ci", None)

        # data
        self.data = data = np.array(data) if isinstance(data, list) else data
        self.alpha = alpha = data2rad(data, n_intervals) if rotate is None else rotate_data(data2rad(data, n_intervals), rotate, unit="radian")

        # data preprocessing
        if bins is None:
            if w is None:  # ungrouped data, because no `w` is provided.
                self.w = w = np.ones_like(alpha).astype(int)
                self.grouped = grouped = False
                self.bin_size = bin_size = 0.0
            else:  # grouped data
                assert len(w) == len(alpha), "`w` and `data` must be the same length."
                assert len(w) == len(
                    np.arange(0, 2 * np.pi, 2 * np.pi / len(w))
                ), "Grouped data should included empty bins."
                self.w = np.array(w) if isinstance(w, list) else w
                self.grouped = grouped = True
                self.bin_size = bin_size = np.diff(alpha).min()
                self.alpha_lb = alpha - bin_size / 2
                self.alpha_ub = alpha + bin_size / 2

        # bin data usingse np.histogram
        else:
            if isinstance(bins, int) or isinstance(bins, np.ndarray):
                w, alpha = np.histogram(
                    alpha, bins=bins, range=(0, 2 * np.pi)
                )  # np.histogram return bin edges
            self.w = w
            self.alpha_lb = alpha[:-1]  # bin lower bound
            self.alpha_ub = alpha[1:]  # bin upper bound
            self.alpha = alpha = 0.5 * (alpha[:-1] + alpha[1:])  # get bin centers
            self.grouped = grouped = True
            self.bin_size = bin_size = np.diff(alpha).min()

        # sample size
        self.n = n = np.sum(w).astype(int)

        # angular mean and resultant vector length
        self.mean, self.r = (_, r) = circ_mean_and_r(alpha=alpha, w=w)

        # z-score and p-value from rayleigh test for angular mean
        self.mean_test_result = rayleigh_test_result = rayleigh_test(n=n, r=r)
        mean_pval = rayleigh_test_result.pval

        # Rayleigh's R
        self.R = n * r

        # kappa
        self.kappa = circ_kappa(r=r, n=n)

        # confidence interval for angular mean
        # in practice, the equations for approximating mean ci for 8 <= n <= 12 in zar 2010
        # can still yield nan
        if self.kwargs_mean_ci is None:
            if mean_pval < 0.05 and (8 <= self.n < 25):
                self.method_mean_ci = method_mean_ci = "bootstrap"
                self.mean_ci_level = mean_ci_level = 0.95
            elif mean_pval < 0.05 and self.n >= 25:
                # Eq 4.22 (Fisher, 1995)
                self.method_mean_ci = method_mean_ci = "dispersion"
                self.mean_ci_level = mean_ci_level = 0.95
            else:  # mean_pval > 0.05
                self.method_mean_ci = method_mean_ci = None
                self.mean_ci_level = mean_ci_level = np.nan
        else:
            self.method_mean_ci = method_mean_ci = kwargs_mean_ci.pop(
                "method", "bootstrap"
            )
            self.mean_ci_level = mean_ci_level = 0.95

        if method_mean_ci is not None and mean_pval < 0.05:
            self.mean_lb, self.mean_ub = mean_lb, mean_ub = circ_mean_ci(
                alpha=self.alpha,
                w=self.w,
                mean=self.mean,
                r=self.r,
                n=self.n,
                ci=mean_ci_level,
                method=method_mean_ci,
            )
        else:
            self.mean_lb, self.mean_ub = np.nan, np.nan

        # angular deviation, circular standard deviation, adjusted resultant vector length (if needed)
        self.s = angular_std(r=r, bin_size=bin_size)
        self.s0 = circ_std(r=r, bin_size=bin_size)

        # angular median
        if n > 10000 and kwargs_median["method"] is not None:
            print(
                "Sample size is large (n>10000), it will take a while to find the median.\nOr set `kwargs_median={'method': None}` to skip."
            )

        self.median = median = circ_median(
            alpha=alpha,
            w=w,
            method=kwargs_median["method"],
            return_average=kwargs_median["return_average"],
            average_method=kwargs_median["average_method"],
        )

        # confidence inerval for angular median (only for ungrouped data)
        # it's unclear how to do it for grouped data.
        if not grouped and not np.isnan(median):
            self.median_lb, self.median_ub, self.median_ci_level = circ_median_ci(
                median=median, alpha=alpha
            )

        self.skewness = circ_skewness(alpha=alpha, w=w)
        self.kurtosis = circ_kurtosis(alpha=alpha, w=w)

        # check multimodality
        self.mixtures = []
        if n_clusters_max > 1:
            for k in range(1, n_clusters_max + 1):
                m = MoVM(
                    n_clusters=k,
                    n_intervals=n_intervals,
                    unit="radian",
                    random_seed=0,
                )
                m.fit(np.repeat(alpha, w))
                self.mixtures.append(m)
            self.mixtures_BIC = [m.compute_BIC() for m in self.mixtures]
            if not np.isnan(self.mixtures_BIC).all():
                self.mixture_opt = self.mixtures[np.nanargmin(self.mixtures_BIC)]
            else:
                self.mixture_opt = None

    def __repr__(self):
        unit = self.unit
        k = self.n_intervals

        docs = "Circular Data\n"
        docs += "=============\n\n"

        docs += "Summary\n"
        docs += "-------\n"
        docs += f"  Grouped?: Yes\n" if self.grouped else f"  Grouped?: No\n"
        if self.n_clusters_max > 1 and self.mixture_opt is not None:
            docs += (
                f"  Unimodal?: Yes \n"
                if len(self.mixture_opt.m) == 1
                else f"  Unimodal?: No (n_clusters={len(self.mixture_opt.m)}) \n"
            )

        docs += f"  Unit: {unit}\n"
        docs += f"  Sample size: {self.n}\n"

        if hasattr(self, "d"):
            docs += f"  Angular mean: {rad2data(self.mean, k=k):.02f} ± {rad2data(self.d, k=k):.02f} ( p={self.mean_test_result.pval:.04f} {significance_code(self.mean_test_result.pval)} ) \n"
        else:
            docs += f"  Angular mean: {rad2data(self.mean, k=k):.02f} ( p={self.mean_test_result.pval:.04f} {significance_code(self.mean_test_result.pval)} ) \n"

        if hasattr(self, "mean_lb") and not np.isnan(self.mean_lb):
            docs += f"  Angular mean CI ({self.mean_ci_level:.2f}): {rad2data(self.mean_lb, k=k):.02f} - {rad2data(self.mean_ub, k=k):.02f}\n"

        docs += f"  Angular median: {rad2data(self.median, k=k):.02f} \n"
        if hasattr(self, "median_lb") and not np.isnan(self.median_lb):
            docs += f"  Angular median CI ({self.median_ci_level:.2f}): {rad2data(self.median_lb, k=k):.02f} - {rad2data(self.median_ub, k=k):.02f}\n"

        docs += f"  Angular deviation (s): {rad2data(self.s, k=k):.02f} \n"
        docs += f"  Circular standard deviation (s0): {rad2data(self.s0, k=k):.02f} \n"
        docs += f"  Concentration (r): {self.r:0.2f}\n"
        docs += f"  Concentration (kappa): {self.kappa:0.2f}\n"
        docs += f"  Skewness: {self.skewness:0.3f}\n"
        docs += f"  Kurtosis: {self.kurtosis:0.3f}\n"

        docs += f"\n"

        docs += "Signif. codes:\n"
        docs += "--------------\n"
        docs += " 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n\n"

        docs += "Method\n"
        docs += "------\n"
        docs += f"  Angular median: {self.kwargs_median['method']}\n"
        docs += f"  Angular mean CI: {self.method_mean_ci}\n"

        return docs

    def __str__(self):
        return self.__repr__()

    def summary(self):
        r"""
        Summary of basic statistics for circular data.

        This method generates a textual summary of the key descriptive and inferential
        statistics computed for the circular data. It provides information about
        the data type, concentration, dispersion, and more.

        The summary includes the following components:

        1. **Grouping**:

            Indicates whether the data is grouped (binned) or ungrouped.

        2. **Unimodality**:

            For models with mixtures of von Mises distributions, it specifies whether
        the data is unimodal or multimodal, along with the number of clusters if applicable.

        3. **Data Characteristics**:

            - The unit of measurement (e.g., degrees, radians, hours).
            - Total sample size, including weights if provided.

        4. **Angular Mean**:

            - The angular mean, with its corresponding p-value from the Rayleigh test.
            - The confidence interval (CI) for the angular mean, if available.

        5. **Angular Median**:

            - The angular median, representing the central tendency.
            - The confidence interval (CI) for the angular median, if applicable.

        6. **Measures of Dispersion**:

            - Angular deviation ($s$): A measure of spread in circular data.
            - Circular standard deviation ($s_0$): An alternative dispersion measure.

        7. **Measures of Concentration**:

            - Resultant vector length ($r$): A measure of data concentration, ranging from 0 (uniform) to 1 (highly concentrated).
            - Concentration parameter ($\kappa$): Indicates sharpness or clustering of the data.

        8. **Higher-Order Statistics**:

            - Circular skewness: A measure of asymmetry.
            - Circular kurtosis: A measure of peakedness or flatness relative to a uniform distribution.

        9. **Significance Codes**:

            - A guide to interpret the p-values of statistical tests.

        10. **Methods**:

            - The method used for calculating the angular median.
            - The method used for estimating confidence intervals for the angular mean.
        """

        return self.__repr__()

    def plot(self, ax=None, kind=None, **kwargs):
        """
        Visualize circular data.

        This method provides various visualization options for circular data, including scatter
        plots, density plots, and rose diagrams. It is a wrapper around the `circ_plot` function.

        Parameters
        ----------
        ax : matplotlib.axes._axes.Axes, optional
            The matplotlib Axes object where the plot will be drawn. If None, a new Axes object
            is created. Default is None.

        kind : str or None, optional
            Deprecated. Use `kwargs` for customizing specific plot types instead. Default is None.

        **kwargs : dict, optional
            Additional parameters for customizing the plot. Examples include:

            - `outward` (bool): Whether scatter points radiate outward. Default is True.
            - `figsize` (tuple): Size of the figure. Default is (5, 5).
            - `projection` (str): Projection type, typically "polar". Default is "polar".
            - `marker` (str): Marker style for scatter points. Default is "o".
            - `marker_color` (str): Color of scatter points. Default is "black".
            - `marker_size` (int): Size of scatter points. Default is 10.
            - `bins` (int): Number of bins for the rose diagram. Default is 12.
            - `plot_density` (bool): Whether to plot density estimation. Default is True.
            - `plot_rose` (bool): Whether to plot a rose diagram. Default is True.
            - `plot_mean` (bool): Whether to plot the angular mean. Default is True.
            - `plot_mean_ci` (bool): Whether to plot confidence intervals for the angular mean. Default is True.
            - `plot_median` (bool): Whether to plot the angular median. Default is True.
            - `plot_median_ci` (bool): Whether to plot confidence intervals for the angular median. Default is True.
            - `zero_location` (str): Zero location on the polar plot ("N", "E", "S", "W"). Default is "N".
            - `clockwise` (int): Direction of the polar axis (-1 for clockwise, 1 for counterclockwise). Default is -1.
            - `r_max_scatter` (float): Maximum radius for scatter points. Default is 1.
            - `rticks` (list): Radial ticks for the polar plot. Default is [0, 1].
            - `rlim_max` (float): Maximum radius for the plot. Default is None.

        Returns
        -------
        ax : matplotlib.axes._axes.Axes
            The matplotlib Axes object containing the plot.

        Notes
        -----
        - This method supports both grouped and ungrouped data.
        - Density estimation can be performed using either nonparametric methods or mixtures
        of von Mises distributions.
        - The rose diagram represents grouped data as a histogram over angular bins.
        - Confidence intervals for the mean and median are plotted as arcs on the circle.

        Examples
        --------
        #### Basic scatter plot

        ```
        data = [30, 60, 90, 120, 150]
        circ = Circular(data, unit="degree")
        circ.plot(marker_color="blue", marker_size=15)
        ```

        #### Rose diagram with density

        ```
        circ.plot(plot_rose=True, plot_density=True, bins=18)
        ```

        #### Customized plot with radial grid and legend

        ```
        circ.plot(plot_grid=True, plot_spine=True, plot_mean=True)
        ```
        """
        ax = circ_plot(self, ax=ax, **kwargs)

summary()

Summary of basic statistics for circular data.

This method generates a textual summary of the key descriptive and inferential statistics computed for the circular data. It provides information about the data type, concentration, dispersion, and more.

The summary includes the following components:

  1. Grouping:

    Indicates whether the data is grouped (binned) or ungrouped.

  2. Unimodality:

    For models with mixtures of von Mises distributions, it specifies whether the data is unimodal or multimodal, along with the number of clusters if applicable.

  3. Data Characteristics:

    • The unit of measurement (e.g., degrees, radians, hours).
    • Total sample size, including weights if provided.
  4. Angular Mean:

    • The angular mean, with its corresponding p-value from the Rayleigh test.
    • The confidence interval (CI) for the angular mean, if available.
  5. Angular Median:

    • The angular median, representing the central tendency.
    • The confidence interval (CI) for the angular median, if applicable.
  6. Measures of Dispersion:

    • Angular deviation (\(s\)): A measure of spread in circular data.
    • Circular standard deviation (\(s_0\)): An alternative dispersion measure.
  7. Measures of Concentration:

    • Resultant vector length (\(r\)): A measure of data concentration, ranging from 0 (uniform) to 1 (highly concentrated).
    • Concentration parameter (\(\kappa\)): Indicates sharpness or clustering of the data.
  8. Higher-Order Statistics:

    • Circular skewness: A measure of asymmetry.
    • Circular kurtosis: A measure of peakedness or flatness relative to a uniform distribution.
  9. Significance Codes:

    • A guide to interpret the p-values of statistical tests.
  10. Methods:

    • The method used for calculating the angular median.
    • The method used for estimating confidence intervals for the angular mean.
Source code in pycircstat2/base.py
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
def summary(self):
    r"""
    Summary of basic statistics for circular data.

    This method generates a textual summary of the key descriptive and inferential
    statistics computed for the circular data. It provides information about
    the data type, concentration, dispersion, and more.

    The summary includes the following components:

    1. **Grouping**:

        Indicates whether the data is grouped (binned) or ungrouped.

    2. **Unimodality**:

        For models with mixtures of von Mises distributions, it specifies whether
    the data is unimodal or multimodal, along with the number of clusters if applicable.

    3. **Data Characteristics**:

        - The unit of measurement (e.g., degrees, radians, hours).
        - Total sample size, including weights if provided.

    4. **Angular Mean**:

        - The angular mean, with its corresponding p-value from the Rayleigh test.
        - The confidence interval (CI) for the angular mean, if available.

    5. **Angular Median**:

        - The angular median, representing the central tendency.
        - The confidence interval (CI) for the angular median, if applicable.

    6. **Measures of Dispersion**:

        - Angular deviation ($s$): A measure of spread in circular data.
        - Circular standard deviation ($s_0$): An alternative dispersion measure.

    7. **Measures of Concentration**:

        - Resultant vector length ($r$): A measure of data concentration, ranging from 0 (uniform) to 1 (highly concentrated).
        - Concentration parameter ($\kappa$): Indicates sharpness or clustering of the data.

    8. **Higher-Order Statistics**:

        - Circular skewness: A measure of asymmetry.
        - Circular kurtosis: A measure of peakedness or flatness relative to a uniform distribution.

    9. **Significance Codes**:

        - A guide to interpret the p-values of statistical tests.

    10. **Methods**:

        - The method used for calculating the angular median.
        - The method used for estimating confidence intervals for the angular mean.
    """

    return self.__repr__()

plot(ax=None, kind=None, **kwargs)

Visualize circular data.

This method provides various visualization options for circular data, including scatter plots, density plots, and rose diagrams. It is a wrapper around the circ_plot function.

Parameters:

Name Type Description Default
ax Axes

The matplotlib Axes object where the plot will be drawn. If None, a new Axes object is created. Default is None.

None
kind str or None

Deprecated. Use kwargs for customizing specific plot types instead. Default is None.

None
**kwargs dict

Additional parameters for customizing the plot. Examples include:

  • outward (bool): Whether scatter points radiate outward. Default is True.
  • figsize (tuple): Size of the figure. Default is (5, 5).
  • projection (str): Projection type, typically "polar". Default is "polar".
  • marker (str): Marker style for scatter points. Default is "o".
  • marker_color (str): Color of scatter points. Default is "black".
  • marker_size (int): Size of scatter points. Default is 10.
  • bins (int): Number of bins for the rose diagram. Default is 12.
  • plot_density (bool): Whether to plot density estimation. Default is True.
  • plot_rose (bool): Whether to plot a rose diagram. Default is True.
  • plot_mean (bool): Whether to plot the angular mean. Default is True.
  • plot_mean_ci (bool): Whether to plot confidence intervals for the angular mean. Default is True.
  • plot_median (bool): Whether to plot the angular median. Default is True.
  • plot_median_ci (bool): Whether to plot confidence intervals for the angular median. Default is True.
  • zero_location (str): Zero location on the polar plot ("N", "E", "S", "W"). Default is "N".
  • clockwise (int): Direction of the polar axis (-1 for clockwise, 1 for counterclockwise). Default is -1.
  • r_max_scatter (float): Maximum radius for scatter points. Default is 1.
  • rticks (list): Radial ticks for the polar plot. Default is [0, 1].
  • rlim_max (float): Maximum radius for the plot. Default is None.
{}

Returns:

Name Type Description
ax Axes

The matplotlib Axes object containing the plot.

Notes
  • This method supports both grouped and ungrouped data.
  • Density estimation can be performed using either nonparametric methods or mixtures of von Mises distributions.
  • The rose diagram represents grouped data as a histogram over angular bins.
  • Confidence intervals for the mean and median are plotted as arcs on the circle.

Examples:

Basic scatter plot
data = [30, 60, 90, 120, 150]
circ = Circular(data, unit="degree")
circ.plot(marker_color="blue", marker_size=15)
Rose diagram with density
circ.plot(plot_rose=True, plot_density=True, bins=18)
Customized plot with radial grid and legend
circ.plot(plot_grid=True, plot_spine=True, plot_mean=True)
Source code in pycircstat2/base.py
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
def plot(self, ax=None, kind=None, **kwargs):
    """
    Visualize circular data.

    This method provides various visualization options for circular data, including scatter
    plots, density plots, and rose diagrams. It is a wrapper around the `circ_plot` function.

    Parameters
    ----------
    ax : matplotlib.axes._axes.Axes, optional
        The matplotlib Axes object where the plot will be drawn. If None, a new Axes object
        is created. Default is None.

    kind : str or None, optional
        Deprecated. Use `kwargs` for customizing specific plot types instead. Default is None.

    **kwargs : dict, optional
        Additional parameters for customizing the plot. Examples include:

        - `outward` (bool): Whether scatter points radiate outward. Default is True.
        - `figsize` (tuple): Size of the figure. Default is (5, 5).
        - `projection` (str): Projection type, typically "polar". Default is "polar".
        - `marker` (str): Marker style for scatter points. Default is "o".
        - `marker_color` (str): Color of scatter points. Default is "black".
        - `marker_size` (int): Size of scatter points. Default is 10.
        - `bins` (int): Number of bins for the rose diagram. Default is 12.
        - `plot_density` (bool): Whether to plot density estimation. Default is True.
        - `plot_rose` (bool): Whether to plot a rose diagram. Default is True.
        - `plot_mean` (bool): Whether to plot the angular mean. Default is True.
        - `plot_mean_ci` (bool): Whether to plot confidence intervals for the angular mean. Default is True.
        - `plot_median` (bool): Whether to plot the angular median. Default is True.
        - `plot_median_ci` (bool): Whether to plot confidence intervals for the angular median. Default is True.
        - `zero_location` (str): Zero location on the polar plot ("N", "E", "S", "W"). Default is "N".
        - `clockwise` (int): Direction of the polar axis (-1 for clockwise, 1 for counterclockwise). Default is -1.
        - `r_max_scatter` (float): Maximum radius for scatter points. Default is 1.
        - `rticks` (list): Radial ticks for the polar plot. Default is [0, 1].
        - `rlim_max` (float): Maximum radius for the plot. Default is None.

    Returns
    -------
    ax : matplotlib.axes._axes.Axes
        The matplotlib Axes object containing the plot.

    Notes
    -----
    - This method supports both grouped and ungrouped data.
    - Density estimation can be performed using either nonparametric methods or mixtures
    of von Mises distributions.
    - The rose diagram represents grouped data as a histogram over angular bins.
    - Confidence intervals for the mean and median are plotted as arcs on the circle.

    Examples
    --------
    #### Basic scatter plot

    ```
    data = [30, 60, 90, 120, 150]
    circ = Circular(data, unit="degree")
    circ.plot(marker_color="blue", marker_size=15)
    ```

    #### Rose diagram with density

    ```
    circ.plot(plot_rose=True, plot_density=True, bins=18)
    ```

    #### Customized plot with radial grid and legend

    ```
    circ.plot(plot_grid=True, plot_spine=True, plot_mean=True)
    ```
    """
    ax = circ_plot(self, ax=ax, **kwargs)