CSV Format

Export narratives as CSV for spreadsheet analysis and data science workflows.

Basic Usage

use spatial_narrative::io::{CsvFormat, Format};

// Export to CSV
let csv = CsvFormat::new().export_str(&narrative)?;

// Import from CSV
let narrative = CsvFormat::new().import_str(&csv)?;

Output Structure

Default CSV output:

latitude,longitude,timestamp,text,tags
40.7128,-74.006,2024-01-15T10:00:00Z,"Conference begins","conference,technology"
40.758,-73.9855,2024-01-15T14:00:00Z,"Press conference","press,media"

Configuration Options

Customize column names and delimiter:

use spatial_narrative::io::{CsvFormat, CsvOptions};

let options = CsvOptions {
    lat_column: "lat".to_string(),
    lon_column: "lng".to_string(),
    timestamp_column: "datetime".to_string(),
    text_column: Some("description".to_string()),
    tags_column: Some("categories".to_string()),
    elevation_column: Some("altitude".to_string()),
    source_title_column: None,
    source_url_column: None,
    delimiter: b',',
};

let format = CsvFormat::with_options(options);
let csv = format.export_str(&narrative)?;

Column Options

OptionDefaultDescription
lat_column"latitude"Latitude column name
lon_column"longitude"Longitude column name
timestamp_column"timestamp"Timestamp column name
text_columnSome("text")Event text column
tags_columnSome("tags")Tags column (comma-separated)
elevation_columnNoneElevation column
source_title_columnNoneSource title column
source_url_columnNoneSource URL column
delimiterb','Field delimiter

TSV (Tab-Separated)

let options = CsvOptions {
    delimiter: b'\t',
    ..Default::default()
};

let tsv = CsvFormat::with_options(options).export_str(&narrative)?;

Importing CSV

Import from existing CSV data:

let csv = r#"lat,lon,time,description
40.7128,-74.006,2024-01-15T10:00:00Z,Conference begins
40.758,-73.9855,2024-01-15T14:00:00Z,Press conference"#;

let options = CsvOptions {
    lat_column: "lat".to_string(),
    lon_column: "lon".to_string(),
    timestamp_column: "time".to_string(),
    text_column: Some("description".to_string()),
    ..Default::default()
};

let narrative = CsvFormat::with_options(options).import_str(csv)?;

Handling Tags

Tags are stored as comma-separated values:

// Export: tags become "tag1,tag2,tag3"
// Import: "tag1,tag2,tag3" becomes HashSet{"tag1", "tag2", "tag3"}

let csv = "latitude,longitude,timestamp,text,tags
40.7128,-74.006,2024-01-15T10:00:00Z,Event,\"conference,technology,important\"";

let narrative = CsvFormat::new().import_str(csv)?;
assert!(narrative.events[0].has_tag("conference"));

File Operations

use std::fs::File;
use std::io::{BufReader, BufWriter};

// Export to file
let file = File::create("events.csv")?;
CsvFormat::new().export(&narrative, &mut BufWriter::new(file))?;

// Import from file
let file = File::open("events.csv")?;
let narrative = CsvFormat::new().import(&mut BufReader::new(file))?;

Integration with Data Tools

Python/Pandas

import pandas as pd

# Read exported CSV
df = pd.read_csv('events.csv', parse_dates=['timestamp'])

# Analyze
print(f"Events: {len(df)}")
print(f"Date range: {df['timestamp'].min()} to {df['timestamp'].max()}")
print(f"Locations: {df[['latitude', 'longitude']].nunique()}")

Excel

CSV files open directly in Excel. For best results:

  • Use UTF-8 encoding
  • Quote text fields containing commas
  • Use ISO 8601 timestamps

R

library(tidyverse)

events <- read_csv("events.csv")

# Plot on map
library(sf)
events_sf <- st_as_sf(events, coords = c("longitude", "latitude"), crs = 4326)
plot(events_sf)

When to Use CSV

Use CSV when:

  • Analyzing data in spreadsheets (Excel, Google Sheets)
  • Using with data science tools (pandas, R)
  • Simple data exchange with minimal overhead
  • Data pipelines that expect tabular formats

Consider other formats when:

  • You need complex metadata → use JSON
  • Mapping in web applications → use GeoJSON
  • Source attribution is important → use JSON

Limitations

CSV has some inherent limitations:

FeatureSupport
Location coordinates✅ Full
Timestamps✅ Full
Event text✅ Full
Tags✅ As comma-separated string
Basic source info⚠️ Optional columns
Custom metadata❌ Not supported
Nested data❌ Not supported