Skip to main content

Column Types and Manipulation

Columns are the core building blocks of every VisiData sheet. This lesson covers type casting, derived columns, column reordering, and the Columns Sheet for bulk metadata editing.

Learning Focus

Focus on: type casting (#%$@~), derived columns (=), and the Columns Sheet (Shift+C). These three unlock most of VisiData's analysis power.

Column Type Casting

Every column starts as string type unless typed explicitly. Type casting affects sorting, aggregation, and display.

KeyTypeWhat it enables
~strText sorting, regex ops
#intNumeric sort, sum/mean
%floatDecimal precision, sum/mean
$currencyFormatted decimal display
@dateChronological sort, date diff
z#lenString length as integer
# Move cursor to 'age' column, press:
# → cast to integer
# Move cursor to 'salary', press:
% → cast to float
# Move cursor to 'created_at', press:
@ → cast to date (auto-detects format)

Column Width

_ toggle width: full vs default
g_ toggle ALL column widths: full vs default
z_ <number> set exact width of current column
gz_ <number> set exact width of all visible columns
- hide current column
g- hide all columns with only one distinct value

Renaming Columns

^ rename current column (opens input prompt)
g^ rename all unnamed columns to content of selected rows
z^ rename current column to combined content of current cell

Reordering Columns

H slide current column left
L slide current column right
gH slide current column to far left
gL slide current column to far right

Hiding and Showing Columns

- hide current column
gv unhide all hidden columns

To see hidden columns, open the Columns Sheet (Shift+C) and look for columns with width=0.

Derived Columns with Python Expressions

Press = to create a new column computed from a Python expression. Column names are available as variables.

# Create a column 'full_name' from first and last name columns
=
# Enter: first_name + ' ' + last_name

# Create 'annual' from monthly salary
=
# Enter: salary * 12

# Create 'domain' from email
=
# Enter: email.split('@')[-1]

# Create 'age_bucket' from age
=
# Enter: 'senior' if age >= 65 else 'adult' if age >= 18 else 'minor'
info

Expression columns are computed on demand — they do not consume extra memory for large datasets.

Set Column Values with g=

# Set all selected rows' 'region' column to 'APAC'
g=
# Enter: 'APAC'

# Set 'status' to 'inactive' for selected rows
g=
# Enter: 'inactive'

Column Split with Regex

: regex split current column into multiple columns by regex
; regex extract capture groups from current column as new columns

Example — split an IP address into octets:

# Move cursor to 'ip' column
:
# Enter: \.
# Creates 4 new columns: ip_1, ip_2, ip_3, ip_4

Extract log fields from a raw log line:

;
# Enter: (?P<ip>\d+\.\d+\.\d+\.\d+) \[(?P<date>[^\]]+)\] "(?P<method>\w+)
# Creates named capture group columns: ip, date, method

The Columns Sheet (Shift+C)

The Columns Sheet lets you view and edit all column properties in one place.

Shift+C
# Shows: name, width, type, key, aggregator
# Press e on any cell to edit it
# Press g+ <aggregator> to set aggregator on selected columns
# Press g! to toggle selected columns as key columns
# Press g- to hide selected columns

Expand Nested Columns

For JSON data with nested dicts or lists:

( expand current column of lists/dicts (one level)
g( expand ALL such columns (one level)
z( <depth> expand to specific depth
) collapse (unexpand) current column

Practical Use Cases

Cast and Analyze Server Logs

vd /var/log/nginx/access.log

# Move to 'bytes_sent' column
#
# Now it sorts numerically
# Press Shift+F for frequency table with counts

Create a Combined Key Column

vd /tmp/servers.csv

# Create hostname_region column
=
# Enter: hostname + '-' + region
# New derived column appears: hostname + '-' + region

Split Email to Extract Domain

vd /tmp/users.csv

# Move to 'email' column
;
# Enter: @(?P<domain>.+)
# New column 'domain' appears

Troubleshooting Matrix

ProblemCauseFix
# cast shows #ERRColumn has non-numeric valuesClean data first or use ~
Date cast wrongFormat not recognizedSet disp_date_fmt in .visidatarc
Expression throws NameErrorColumn name has spacesUse col['column name'] syntax
Derived column shows NoneExpression returns None for some rowsAdd a default: x or 'unknown'

Best Practices

  • Always cast numeric columns before sorting or aggregating — string sort of numbers gives wrong results.
  • Use ; with named capture groups for structured log parsing — much faster than hand-splitting in Python.
  • Use the Columns Sheet (Shift+C) for bulk type changes across many columns at once.

Hands-On Practice

vd /tmp/servers.csv

# 1. Move to 'hostname', press ^ and rename it to 'host'
# 2. Move to 'region', press ! to make it a key column
# 3. Press = and enter: hostname + '_' + region
# 4. Name it 'id' when prompted
# 5. Press Shift+C to view the Columns Sheet
# 6. Edit the 'width' of any column
# 7. Press q to return

What's Next