cleave: Align data from separate spines into new fields.

View source: R/Reshape.R

cleaveR Documentation

Align data from separate spines into new fields.

Description

Cleave, as in "to cleave together," moves data from separate spines (or paths) into new fields in the same spine(s). Under the hood, cleave() essentially runs a specialized call to make the humdrum table "wider," similar to R functions like cast(), spread(), or pivot_wider(). In fact, a humdrumR method for pivot_wider() is defined, which is equivalent to cleave(). The cleave() function is essentially the inverse of rend().

Usage

cleave(humdrumR, ..., field = selectedFields(humdrumR)[1], newFields = NULL)

## S3 method for class 'humdrumR'
pivot_wider(data, names_from = "Spine", values_from = selectedFields(data)[1])

cleaveSpines(humdrumR, field = selectedFields(humdrumR)[1])

cleavePaths(humdrumR, field = selectedFields(humdrumR)[1])

cleaveStops(humdrumR, field = selectedFields(humdrumR)[1])

Arguments

humdrumR

HumdrumR data.

Must be a humdrumR data object.

...

What to cleave?

Must be natural numbers, character strings representing exclusive interpretations, or lists of either.

field

Which field cleave data from.

Defaults to first selected field.

Must be a character string partially matching the name of a data field in the humdrumR input. For example, "Tok" would match the Token field.

newFields

Names to use for new fields created by the cleave.

By default generates names by structure/number (like Spine2) or exclusive interpretation (like Silbe).

Must be non-empty character string.

Details

Many humdrum datasets encode data across multiple spines, spine-paths, or stops. By default, humdrumR parses each separate spine, spine-path, and stop as their own individual data points, taking up one row in the humdrum table. If we want to treat data in multiple spines/paths/stops as different aspects of the same data it is easiest to reshape the data so that the information is in different humdrumR fields rather than separate spines/paths/stops. In the humdrum syntax view, the spines (or path/stops) are moved "on top" of each other, cleaving them together.

The convenient cleaveSpines(), cleaveStops(), and cleavePaths() functions automatically cleave all stops/paths in a dataset onto the first spine/stop/path, creating new fields named, e.g., Path1, Path2, etc.

Syntax

The cleave() function takes any number of ... arguments specifying groups of spines/paths/stops to cleave together.

  • cleave(humData, Spine = 1:2) will cleave the first and second spine.

  • cleave(humData, Spine = 1:4) will cleave the first four spines.

  • cleave(humData, Spine = 1:2, Spine = 3:4) will cleave spine 1 with spine 2, and separately, spine 3 with spine 4.

The default is to cleave spines, so you can actually omit the ⁠Spine = ⁠ part: e.g., cleave(humData, 1:2) is the same as cleave(humData, Spine = 1:2). If you want to cleave spine paths, you'll need to explicitly call something like cleave(humData, Path = 0:1). The first element in each group is used as the original location which all other spines/paths/stops are cleaved into. The ordering of the remaining elements is irrelevant.

Piece-specific cleaving

By default, the same cleaving will be applied in all pieces (if the pieces have the target spines/paths/stops). However, you can use an alternate argument structure to apply differerent cleaves to different pieces. To do so, provide groups to cleave arguments in a list, with each element in the list representing cleave group in one piece. If the listed groups are unnamed, the groups are mapped to pieces by index. For example, the call cleave(humData, list(1:2, 2:3, 3:4, NULL, 1:3)) will result in the following cleaves:

  • In piece 1, cleave spines 1 and 2.

  • In piece 2, cleave spines 2 and 3.

  • In piece 3, cleave spines 3 and 4.

  • In piece 4, no cleave (no changes).

  • In piece 5, cleave the first three spines.

  • In any remaining pieces (6 or greater), no cleaves.

Alternatively, you can name the list elements with integers corresponding to pieces. For example, ⁠cleave(humData, Path = list("1" = 0:1, 5 = 0:2"))⁠ will cleave paths 0 and 1 in piece 1, and paths 0:2 in piece 5.

Exclusive interpretations

When cleaving spines, you can specify spines using character strings representing exclusive interpretations. So you can call cleave(humData, c('kern', 'silbe')), which will cause ⁠**kern⁠ and ⁠**silbe⁠ spines in each piece to be cleaved. Note that any exclusive interpretations which aren't "mentioned" in the call remain in their original field.

The behavior of exclusive cleaving depends on the relative number of each target exclusive interpretation in each piece. If there are equal numbers of each interpretation, the spines are grouped in parallel. For example, if a piece has the spines ⁠**kern **silbe **kern **silbe⁠, the command cleave(humData, c('kern', 'silbe')) will see that there are two ⁠**kern⁠/⁠**silbe⁠ pairs, and cleave them just like cleave(humData, 1:2, 3:4).

If there are different numbers of spines matching each exclusive interpretation, the cleave behavior depends on which field is the first field in your input argument—we'll call that the "target" exclusive. Consider a file with spines ⁠**kern **kern **harm⁠. If we specify a cleave call cleave(humData, c('kern', 'harm')) that means we want ⁠**kern⁠ to be the "target" exclusive. Since there are fewer ⁠**harm⁠ spines than ⁠**kern⁠ spines, the data in the ⁠**harm⁠ spine will be duplicated, can cleaved to both ⁠**kern⁠ spines in parallel. If we instead call cleave(humData, c('harm', 'kern')), making ⁠**harm⁠ the "target", the two ⁠**kern⁠ spines will both be "piled" atop the single ⁠**harm⁠ spine, making two new ⁠**kern⁠ fields.

Fields

Cleaving can (for now) only be applied to one field in our data, which defaults to the first selected field; You can change the target field with the field argument.

Cleaving will always introduce new fields into your data. The first spine/path/stop in each cleave group is left in it's original (target) field. Other spine/path/stops will be put into new fields. So if you call humData |> select(Token) |> cleave(humData, 1:2), spine 1 will remain in the Token field and spine 2 data will be put in a new field. By default, the new field(s) will be automatically named by appending the type of cleave (spine vs path vs stop) to the number. In the cleave(humData, 1:2) case, the new field will be called Spine2. You can control the name with the newFields argument, which must be a character vector. You can provide as many new field names as there will be new fields. If you provide too few field names, your name(s) will have numbers appended as necceasary to cover all the new fields; If you provide too many field names, the extra names will simply be ignored.

When cleaving by exclusive interpretation newFields can be used in the exact same way. However, by default (if newFields is NULL), cleave() will names fields by their exclusive interpretation. Note that the original target field (specified by the field) argument will not have it's name changed. So for example, humData |> select(Token) |> cleave(humData, c('kern', 'silbe')) will result in the spines Token and Silbe. No Kern field is created, because the Kern data is left in the Token field.

See Also

The complement/opposite of cleave() is rend(). The collapse family of functions serves a somewhat similar function to cleave().

Other Humdrum table reshaping functions: collapseHumdrum(), expandPaths(), rend()

Other Humdrum table pivoting functions: rend()

Examples


humData <- readHumdrum(humdrumRroot, "HumdrumData/MozartVariations/.*.krn")


humData |> cleave(3:4)
humData |> cleave(Path = 0:1, newFields = 'Ossia')
humData |> cleavePaths()

humData |> cleave(c('function', 'harm'), newFields = 'Harmony')

humData |> cleave(c('kern', 'function', 'harm'))


Computational-Cognitive-Musicology-Lab/humdrumR documentation built on Oct. 22, 2024, 9:28 a.m.