Skip to content

Commit 2cc670e

Browse files
committed
docs: Add value split FCAR recipe
1 parent d85d2ce commit 2cc670e

2 files changed

Lines changed: 306 additions & 0 deletions

File tree

.yardopts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ doc/file_registry_entry.md
1111
doc/cli.md
1212
doc/common_patterns_tips_tricks.md
1313
doc/cookbook.md
14+
doc/fcar_recipes.md
1415
doc/iterative_cleanup.md
1516
doc/kiba_extend_concepts.md
1617
doc/troubleshooting.md

doc/fcar_recipes.md

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
<!--
2+
# @markup markdown
3+
# @title FCAR recipes
4+
-->
5+
6+
# FCAR (facilitated cleanup and remapping) recipes
7+
8+
This page documents common patterns of client FCAR using kiba-extend's iterative cleanup functionality.
9+
10+
Each recipe has three components:
11+
12+
- Prep/setup job - the structure of the data required as input for the FCAR process, and any transforms that exist to streamline achieving this structure
13+
- FCAR configuration - A commented version of the configuration Module to include in your project to activate this FCAR
14+
- Merge job - patterns for merging the FCAR back into the rest of your project
15+
16+
**Table of contents**
17+
18+
- [Review and correction of programmatic value splitting](#review-and-correction-of-programmatic-value-splitting)
19+
* [Prep/setup job](#prepsetup-job)
20+
+ [Normalization job example](#normalization-job-example)
21+
+ [Prep example](#prep-example)
22+
* [FCAR configuration](#fcar-configuration)
23+
* [Merge job](#merge-job)
24+
25+
## Review and correction of programmatic value splitting
26+
27+
The prep and merge sections below use `:init__prep` as the job output from which we are peeling off this FCAR proccess, and thus to which we are merging its results back in.
28+
29+
### Prep/setup job
30+
31+
To ease the merge process, it's recommended you break this into two jobs:
32+
33+
- normalize: normalizes the values to be included in the worksheet
34+
- prep: deduplicates on normalized values and finalizes prep for the split FCAR
35+
36+
#### Normalization job example
37+
38+
In this example, we are pulling just the location field values out of a single migrating table and applying [the normalization described in the worksheet instructions](https://github.com/lyrasis/kiba-extend/blob/main/fcar_instructions/split_values.adoc#details-on-data-preprocessing-done-prior-to-preparing-this-worksheet) to them.
39+
40+
~~~ ruby
41+
# frozen_string_literal: true
42+
43+
module Project
44+
module Jobs
45+
module ValueSplit
46+
module FcarNorm
47+
module_function
48+
49+
def job
50+
Kiba::Extend::Jobs::Job.new(
51+
files: {
52+
source: :init__prep,
53+
destination: :value_split__fcar_norm
54+
},
55+
transformer: xforms
56+
)
57+
end
58+
59+
def xforms
60+
Kiba.job_segment do
61+
transform Delete::FieldsExcept,
62+
fields: %i[location]
63+
transform FilterRows::FieldPopulated,
64+
action: :keep,
65+
field: :location
66+
transform Deduplicate::Table,
67+
field: :location
68+
69+
# Adjust the normalization in a way that makes sense for the data.
70+
# We want to be as aggressive as we can in normalizing, without
71+
# starting to over-lump things that should be kept discrete
72+
transform Normalize::FieldValues,
73+
fields: :location,
74+
targets: :norm,
75+
xforms: [:lower],
76+
replacements: {
77+
/ +/ => " ",
78+
/^ / => "",
79+
/ $/ => ""
80+
}
81+
transform Replace::NormWithMostFrequentlyUsedForm,
82+
normfield: :norm,
83+
nonnormfield: :location,
84+
target: :normloc
85+
transform Delete::Fields,
86+
fields: :norm
87+
end
88+
end
89+
end
90+
end
91+
end
92+
end
93+
~~~
94+
95+
#### Prep example
96+
97+
~~~ ruby
98+
# frozen_string_literal: true
99+
100+
module Project
101+
module Jobs
102+
module ValueSplit
103+
module FcarPrep
104+
module_function
105+
106+
def job
107+
Kiba::Extend::Jobs::Job.new(
108+
files: {
109+
source: :value_split__fcar_norm,
110+
destination: :value_split__fcar_prep
111+
},
112+
transformer: xforms
113+
)
114+
end
115+
116+
def xforms
117+
Kiba.job_segment do
118+
transform Deduplicate::Table,
119+
field: :normloc,
120+
include_occs: true,
121+
compile_uniq_fieldvals: true
122+
transform Rename::Fields, fieldmap: {
123+
location: :unnormalizedlocations
124+
}
125+
126+
# Set up the splitters you need here
127+
transform Fcar::SplitPrep,
128+
orig: :normloc,
129+
splitters: {
130+
/ *; */ => :semicolon,
131+
/ and /i => :and,
132+
/ & / => :ampersand
133+
}
134+
transform Sort::ByFieldValue,
135+
field: :sort,
136+
mode: :string
137+
end
138+
end
139+
end
140+
end
141+
end
142+
end
143+
~~~
144+
145+
### FCAR configuration
146+
147+
~~~ ruby
148+
# frozen_string_literal: true
149+
150+
module Project
151+
module ValueSplit
152+
module_function
153+
154+
# Most of these settings/variables are documented in:
155+
# https://lyrasis.github.io/kiba-extend/Kiba/Extend/Mixins/IterativeCleanup.html
156+
157+
# Job key of the prep job to be used as input for the FCAR. Change this
158+
# to whatever you have named the job in your project.
159+
def base_job = :value_type__split_prep
160+
161+
# Don't change this without good reason. The values used to uniquely
162+
# identify a corrected worksheet row
163+
def fingerprint_fields = %i[split_val orig]
164+
165+
extend Kiba::Extend::Mixins::IterativeCleanup
166+
167+
def orig_values_identifier = :prepped_row_fingerprint
168+
169+
# Edit this to work with the tags in your project
170+
def job_tags = %i[value_type split cleanup]
171+
172+
# Edit this if your worksheet data includes other headers you wish to
173+
# include in the ordering
174+
def worksheet_field_order = %i[split_val orig split to_review
175+
sort]
176+
177+
# Delete this if you aren't including an occurrences field or other
178+
# field that should be collated. These include any fields that indicate
179+
# in what field(s) a term was used; the unnormalized forms of name that
180+
# may have been normalized to create the "orig" value for the FCAR
181+
# process, etc.
182+
def collate_fields = %i[occurrences]
183+
184+
# Delete this if you aren't including a numeric occurrences collated field
185+
# that needs to be summed.
186+
def cleaned_uniq_post_xforms
187+
bind = binding
188+
189+
Kiba.job_segment do
190+
mod = bind.receiver
191+
192+
transform Kiba::Extend::Transforms::Fcar::Helpers::SumCollatedOccurrences,
193+
field: :occurrences,
194+
delim: mod.collation_delim
195+
end
196+
end
197+
198+
def final_post_xforms
199+
Kiba.job_segment do
200+
# Get rid of worksheet fields required for merging back into project
201+
# that could have been modified by client, and the helper
202+
# `autosplit` column
203+
transform Delete::Fields,
204+
fields: %i[orig sort autosplit]
205+
# Reconstitute the original values of fields critical for merging from
206+
# the prepped row fingerprint, and delete the fingerprint field, as
207+
# it has served its purpose
208+
transform Fingerprint::Decode,
209+
fingerprint: :prepped_row_fingerprint,
210+
source_fields: %i[orig split_val sort],
211+
delete_fp: true
212+
transform Rename::Fields, fieldmap: {
213+
fp_orig: :orig,
214+
fp_sort: :sort
215+
}
216+
# We don't need the uncorrected `split_val` values from the
217+
# fingerprint
218+
transform Delete::Fields,
219+
fields: :fp_split_val
220+
# Drop rows where client has deleted values from `split_val`
221+
transform FilterRows::FieldPopulated,
222+
action: :keep,
223+
field: :split_val
224+
# This and the following Deduplicate::Table step exist to
225+
# prevent duplicate values being merged into the project
226+
# if/when client has entered corrected split on all
227+
# rows for the original data
228+
transform CombineValues::FromFieldsWithDelimiter,
229+
sources: %i[orig split_val],
230+
target: :combined,
231+
delete_sources: false,
232+
delim: " "
233+
transform Deduplicate::Table,
234+
field: :combined,
235+
delete_field: true
236+
# Set up so merging will keep values in their original order
237+
transform Sort::ByFieldValue,
238+
field: :sort,
239+
mode: :string
240+
end
241+
end
242+
243+
def final_lookup_on_field = :orig
244+
end
245+
end
246+
~~~
247+
248+
### Merge job
249+
250+
This job replaces the `location` values in the original `:init__prep` output with the correctly and unambiguously delimited values from the FCAR worksheet.
251+
252+
~~~ ruby
253+
# frozen_string_literal: true
254+
255+
module Project
256+
module Jobs
257+
module ValueSplit
258+
module FcarMerge
259+
module_function
260+
261+
def job
262+
Kiba::Extend::Jobs::Job.new(
263+
files: {
264+
source: :init__prep,
265+
destination: :value_split__fcar_merge,
266+
lookup: [
267+
{jobkey: :value_split__fcar_norm, lookup_on: :location},
268+
{jobkey: :value_split__final, lookup_on: :orig}
269+
]
270+
},
271+
transformer: xforms
272+
)
273+
end
274+
275+
def xforms
276+
Kiba.job_segment do
277+
# First, merge the normalized form of each location into the table
278+
transform Merge::MultiRowLookup,
279+
lookup: loc_split__fcar_norm,
280+
keycolumn: :location,
281+
fieldmap: {normloc: :normloc}
282+
283+
# Delete the old location field once normalized forms are merged in, since
284+
# we are replacing with correct forms in a minute
285+
transform Delete::Fields, fields: :location
286+
287+
# Merge in corrected values, matching on the normalized locations we just
288+
# merged in, and the normalized locations in the "orig" column of the FCAR
289+
transform Merge::MultiRowLookup,
290+
lookup: loc_split__final,
291+
keycolumn: :normloc,
292+
fieldmap: {location: :split_val},
293+
delim: Sr.delim
294+
295+
# We don't need to keep the normalized location now that we've matched on it
296+
transform Delete::Fields,
297+
fields: :normloc
298+
end
299+
end
300+
end
301+
end
302+
end
303+
end
304+
305+
~~~

0 commit comments

Comments
 (0)