csvmatch

repository·master·Indexed 41 days ago

https://github.com/maxharlow/csvmatch

A tool for finding fuzzy matches between CSV or Parquet files to connect entities written differently. Version 2.1.0 supports various matching methods including literal, Levenshtein, Jaro, Metaphone, and Bilenko, with configurable thresholds and join types (inner, left-outer, right-outer, full-outer). It features an --ignore flag to disregard case, non-alphabetic characters, and word order, as well as blocking techniques for improved performance on large datasets.

Tokens
3.1K
Snippets
14
Records
15
Agent score
51%

What's inside csvmatch

  1. Implement Blocking for performance and precision

    master

    Blocking is an advanced technique where multiple matches are performed in sequence. Each subsequent match only applies to the subset of results from the previous match. This makes matching faster and more precise for large datasets.

    To implement blocking, you provide lists of arguments (fields, ignores, methods, and thresholds). If you provide fewer values than there are blocks, the last specified value is reused for all subsequent blocks. You can use --verbose to verify how your blocks are being parsed.

    # Example: Block 1 (case-insensitive surname match) -> Block 2 (Levenshtein forename match)
    $ csvmatch \
        data1.csv \
        data2.csv \
        --fields1 name \
        --fields2 'Person Name' \
        --ignore case words-leading \
        --ignore words-tailing \
        --method literal levenshtein \
        > matches.csv
  2. Install csvmatch via pipx

    master

    The recommended installation method is using pipx. If you encounter installation errors, it is likely due to an unsupported Python version. You can specify a required version using the --python flag. If the command is not found after installation, run pipx ensurepath.

    # Install via pipx
    pipx install csvmatch
    
    # If you need to specify a specific Python version
    pipx install --python 3.x --fetch-missing-python csvmatch
    
    # If 'command not found' occurs after installation
    pipx ensurepath
  3. Run an exact match between two files

    master

    To perform a basic exact match, provide the two input files (CSV or Parquet) as arguments, followed by --fields1 and --fields2 to specify the columns to compare. Wrap column names in quotes if they contain spaces. The output is written to stdout and can be redirected to a CSV file.

    $ csvmatch \
        data1.csv \
        data2.csv \
        --fields1 name \
        --fields2 'Person Name' \
        > matches.csv
  4. Use the csvmatch CLI to match files

    master

    The csvmatch command-line tool allows you to compare two files (CSV or Parquet) and perform fuzzy or literal matching on specific columns. It supports various join types and matching algorithms like Levenshtein or Jaro.

    Basic Usage:

    csvmatch [options] FILE1 FILE2

    Key Capabilities:

    • File Formats: Supports .csv and .parquet files.
    • Encoding: Automatically detects encoding for CSV files, or you can specify it manually using --enc1 or --enc2.
    • Join Types: Supports inner, left-outer, right-outer, and full-outer joins via the --join flag.
    • Output Control: Use --output to select specific columns from the source files (prefixed with 1. or 2.), include all columns from a file (1* or 2*), or include the match strength (degree).
    csvmatch FILE1.csv FILE2.csv
  5. Configure csvmatch matching methods and thresholds

    master

    You can control how records are matched using the --method and --threshold flags.

    Matching Methods (--method):

    • literal: Exact string matching (default).
    • levenshtein (or leven): Edit distance matching.
    • jaro: Jaro similarity matching.
    • metaphone: Phonetic matching.
    • bilenko: Bilenko similarity matching.

    Thresholds (--threshold): Specify a number between 0 and 1 representing the minimum similarity required for a match. If multiple thresholds are provided, they are applied to the corresponding methods.

    Example: To use Levenshtein matching with a threshold of 0.8:

    csvmatch --method levenshtein --threshold 0.8 FILE1.csv FILE2.csv
    csvmatch --method levenshtein --threshold 0.8 FILE1.csv FILE2.csv
  6. Configure matching methods and thresholds

    master

    Method Categories

    1. Compared Methods: Compares every row from file 1 with every row from file 2. Complexity grows exponentially with file size.

      • literal: (Default) Exact string match after ignores are applied.
      • levenshtein: Uses Damerau-Levenshtein distance. Good for typos.
      • jaro: Uses Jaro-Winkler distance. Better for shorter strings.
    2. Applied Methods: Transforms text into a representation before matching. Faster, but does not generate a matching degree.

      • metaphone: Uses Double Metaphone phonetic encoding. Good for transcribed/transliterated data.
    3. Custom Methods

      • bilenko: Uses the Dedupe library. Requires user training with positive and negative match examples.
    # Example: Using Levenshtein distance
    $ csvmatch data1.csv data2.csv --fields1 name --fields2 'Person Name' --method levenshtein
    
    # Example: Using Metaphone phonetic matching
    $ csvmatch data1.csv data2.csv --fields1 name --fields2 'Person Name' --method metaphone
  7. Use --ignore to disregard specific data characteristics

    master

    Available ignore characteristics:

    • case: Ignores capitalization.
    • nonalpha: Ignores anything that isn't a number or a letter.
    • nonlatin: Ignores non-Latin characters (e.g., Jérôme matches Jerome).
    • words-leading: Ignores all words except the last (useful for surnames).
    • words-tailing: Ignores all words except the first.
    • words-order: Ignores the order of words (useful for surname-first vs forename-first).
    • titles: Ignores common English name prefixes like Mr or Ms.
    • regex=EXPRESSION: Ignores terms matching a specific regular expression (e.g., --ignore 'regex= Esq$').
    # Example: Ignore case and non-alphanumeric characters
    $ csvmatch data1.csv data2.csv --fields1 name --fields2 'Person Name' --ignore case --ignore nonalpha
    
    # Example: Ignore specific regex pattern
    $ csvmatch data1.csv data2.csv --fields1 name --fields2 'Person Name' --ignore 'regex= Esq$'
  8. Specify matching fields with --fields1 and --fields2

    master

    The --fields1 and --fields2 arguments define which columns from the first and second files should be used for the match.

    • You can provide multiple columns separated by spaces.
    • The columns must be in the same order for both files (the first column in --fields1 is compared against the first column in --fields2, etc.).
    • If a column name contains spaces, wrap it in quotes.
    • If omitted, all columns are compared by default.
    • This flag can be specified multiple times to implement blocking.
    $ csvmatch \
      data1.csv \
      data2.csv \
      --fields1 name place \
      --fields2 'Person Name' Location \
      > matches.csv
  9. Select join types with --join

    master

    Available join types:

    • inner: (Default) Only returns rows that successfully matched.
    • left-outer: Returns everything from the first file; non-matches from the second file will be blank.
    • right-outer: Returns everything from the second file; non-matches from the first file will be blank.
    • full-outer: Returns everything from both files.
    # Example: Perform a left-outer join to keep all rows from data1.csv
    $ csvmatch data1.csv data2.csv --fields1 name --fields2 'Person Name' --join left-outer
  10. Customize output columns with --output

    master

    The --output argument allows you to specify which columns appear in the resulting CSV. Columns are prefixed with 1. or 2. to indicate their source file.

    Special column identifiers:

    • 1*: All columns from the first file.
    • 2*: All columns from the second file.
    • degree: The matching degree number (if using a method that generates one).
    # Example: Output all columns from file 2, then codename from file 1, then the match degree
    $ csvmatch data1.csv data2.csv --fields1 name --fields2 'Person Name' --method levenshtein --output '2*' 1.codename degree
  11. Ignore properties in csvmatch

    master

    The --ignore flag allows you to strip certain characteristics from strings before matching. You can provide multiple ignore properties using the -i flag.

    Supported Properties:

    • c or case: Ignore character case.
    • na or nonalpha: Ignore non-alphabetic characters.
    • nl or nonlatin: Ignore non-Latin characters.
    • wl or words-leading: Ignore leading whitespace/words.
    • wt or words-tailing: Ignore trailing whitespace/words.
    • wo or words-order: Ignore word order.
    • t or titles: Ignore titles.
    • r=EXPRESSION or regex=EXPRESSION: Ignore strings matching a specific regular expression.

    Note: If you provide a filename after regex=, csvmatch will read the regex patterns from that file (one per line).

    Example: Ignore case and non-alphabetic characters:

    csvmatch -i case -i nonalpha FILE1.csv FILE2.csv
  12. Reference: csvmatch CLI flags

    master

    The following flags are available for the csvmatch command:

    FlagMetavarDescription
    -v, --versionPrint version information
    -V, --verbosePrint more information
    --enc1ENCODINGEncoding of the first file (default: autodetect)
    --enc2ENCODINGEncoding of the second file (default: autodetect)
    -1, --fields1FIELDColumn names from the first file to match on (space-separated, default: all)
    -2, --fields2FIELDColumn names from the second file to match on (space-separated, default: all)
    -i, --ignorePROPERTYProperties to ignore (see Ignore Properties)
    -j, --joinTYPEJoin type: inner, left-outer, right-outer, full-outer (default: inner)
    -m, --methodMETHODMatching method: literal, levenshtein, jaro, metaphone, bilenko (default: literal)
    -t, --thresholdTHRESHOLDMatch threshold (0 to 1) (default: 0.6)
    -o, --outputFIELDFields to include in output (e.g., 1.col, 1*, 2*, degree)
    # Example using specific fields and a left-outer join
    csvmatch --fields1 name --fields2 user_name --join left-outer FILE1.csv FILE2.csv