PerspectiveExamples

NYPD CCRB

3-panel dashboard of Datagrid and 2 × Heatmap: Data grid of ComplaintID, grouped by FADOType and Allegation, sorted by ComplaintID; Heatmap chart of ComplaintID, grouped by bucket("IncidentDate", 'Y'), split by month_of_year("IncidentDate"), filtered to IncidentDate > 1985-01-01, IncidentDate < 2025-01-01, with 2 computed expression columns; Heatmap chart of ComplaintID, grouped by month_of_year("IncidentDate"), split by day_of_week("IncidentDate"), filtered to IncidentDate > 1985-01-01, IncidentDate < 2025-01-01, with 3 computed expression columns.

Civilian complaints against NYPD officers.

NYPD CCRB: 3-panel dashboard of Datagrid and 2 × Heatmap: Data grid of ComplaintID, grouped by FADOType and Allegation, sorted by ComplaintID; Heatmap chart of ComplaintID, grouped by bucket("IncidentDate", 'Y'), split by month_of_year("IncidentDate"), filtered to IncidentDate > 1985-01-01, IncidentDate < 2025-01-01, with 2 computed expression columns; Heatmap chart of ComplaintID, grouped by month_of_year("IncidentDate"), split by day_of_week("IncidentDate"), filtered to IncidentDate > 1985-01-01, IncidentDate < 2025-01-01, with 3 computed expression columns.

Data

The NYCLU's database of civilian complaints against NYPD officers, loaded from Apache Arrow and cross-filtered in the browser with no server.

Loaded from /data/nypdccrb.arrow as arrow into the perspective-server engine.

Configuration

This example is a saved <perspective-viewer> workspace. Pass this JSON to viewer.restoreWorkspace() to reproduce it over the same table:

{
    "active": "PERSPECTIVE_GENERATED_ID_1",
    "layout": {
        "type": "split-layout",
        "children": [
            {
                "type": "tab-layout",
                "tabs": [
                    "PERSPECTIVE_GENERATED_ID_1"
                ],
                "selected": 0
            },
            {
                "type": "split-layout",
                "children": [
                    {
                        "type": "tab-layout",
                        "tabs": [
                            "PERSPECTIVE_GENERATED_ID_2"
                        ],
                        "selected": 0
                    },
                    {
                        "type": "tab-layout",
                        "tabs": [
                            "PERSPECTIVE_GENERATED_ID_3"
                        ],
                        "selected": 0
                    }
                ],
                "sizes": [
                    0.5,
                    0.5
                ],
                "orientation": "vertical"
            }
        ],
        "sizes": [
            0.25,
            0.75
        ],
        "orientation": "horizontal"
    },
    "panels": {
        "PERSPECTIVE_GENERATED_ID_1": {
            "plugin": "Datagrid",
            "table": "ccrb",
            "title": "Filter",
            "group_by": [
                "FADOType",
                "Allegation"
            ],
            "sort": [
                [
                    "ComplaintID",
                    "desc"
                ]
            ],
            "columns": [
                "ComplaintID"
            ],
            "aggregates": {
                "ComplaintID": "distinct count"
            }
        },
        "PERSPECTIVE_GENERATED_ID_2": {
            "plugin": "Heatmap",
            "table": "ccrb",
            "title": "Year vs Month of Incident",
            "group_by": [
                "bucket(\"IncidentDate\", 'Y')"
            ],
            "split_by": [
                "month_of_year(\"IncidentDate\")"
            ],
            "filter": [
                [
                    "IncidentDate",
                    ">",
                    "1985-01-01"
                ],
                [
                    "IncidentDate",
                    "<",
                    "2025-01-01"
                ]
            ],
            "group_rollup_mode": "flat",
            "split_rollup_mode": "flat",
            "expressions": {
                "bucket(\"IncidentDate\", 'Y')": "bucket(\"IncidentDate\", 'Y')",
                "month_of_year(\"IncidentDate\")": "month_of_year(\"IncidentDate\")"
            },
            "columns": [
                "ComplaintID"
            ],
            "aggregates": {
                "ComplaintID": "distinct count"
            }
        },
        "PERSPECTIVE_GENERATED_ID_3": {
            "plugin": "Heatmap",
            "table": "ccrb",
            "title": "Month vs Weekday of Incident",
            "group_by": [
                "month_of_year(\"IncidentDate\")"
            ],
            "split_by": [
                "day_of_week(\"IncidentDate\")"
            ],
            "filter": [
                [
                    "IncidentDate",
                    ">",
                    "1985-01-01"
                ],
                [
                    "IncidentDate",
                    "<",
                    "2025-01-01"
                ]
            ],
            "expressions": {
                "month_of_year(\"IncidentDate\")": "month_of_year(\"IncidentDate\")",
                "bucket(\"IncidentDate\", 'Y')": "bucket(\"IncidentDate\", 'Y')",
                "day_of_week(\"IncidentDate\")": "day_of_week(\"IncidentDate\")"
            },
            "columns": [
                "ComplaintID"
            ],
            "aggregates": {
                "ComplaintID": "distinct count"
            }
        }
    }
}

About Perspective

Perspective is an open-source, WebAssembly-powered data grid, pivot table and charting component for large, real-time and streaming datasets — in the browser, Python, Jupyter, Node.js and Rust.

Documentation