> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/sdgm/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/sdgm/_mcp/server.

# Best Practices

> Best practices for data preparation with Kumo Relational

Use these table-design patterns before constructing a relational graph. Define
entity boundaries, join keys, event times, and column types to match the
prediction task.

## Table Structure and Entity Design

An entity table represents a type of object, such as a user or policy.
An event table represents actions or observations over time, such as transactions or claims.

1. **Model one entity type or event type per table.**
   Keeping each type in its own table makes its identifiers, attributes, and relationships unambiguous.

   ```python
   # Good: Separate users from transaction events
   users = df[['user_id', 'user_name', 'user_email']]
   transactions = df[['transaction_id', 'user_id', 'amount', 'timestamp']]

   # Avoid: Mixing entities in one table
   mixed_data = df[['user_id', 'user_name', 'transaction_id', 'amount']]
   ```

2. **Use a single event-time column per table.**
   A single timestamp gives each event table one clear time axis for prediction.

   ```python
   # Good: Split tables with multiple timestamps
   policies = df[['policy_id', 'user_id', 'start_date', 'policy_type']]
   claims = df[['claim_id', 'policy_id', 'claim_date', 'claim_amount']]

   # Avoid: Multiple time columns in one table
   mixed_times = df[['policy_id', 'start_date', 'claim_date', 'end_date']]
   ```

3. **Model many-to-many relationships with junction tables.**
   A junction table stores one row per relationship between records in two other tables.

   ```python
   # Good: Junction table pattern
   users = df[['user_id', 'user_name']]
   skills = df[['skill_id', 'skill_name']]
   user_skills = df[['user_skill_id', 'user_id', 'skill_id', 'proficiency']]
   ```

## Data Preparation

1. **Set pandas dtypes before creating a graph.**
   These dtypes control how pandas stores each column and provide Kumo with a reliable starting point for type inference.

   ```python
   # Good: Set pandas dtypes first
   df['user_id'] = df['user_id'].astype('int64')
   df['category'] = df['category'].astype('string')
   df['timestamp'] = pd.to_datetime(df['timestamp'])
   ```

2. **Use consistent naming conventions.**
   Give matching key columns the same name across tables so relationships are easier to define and review.

   ```python
   # Good: Consistent foreign key naming
   users.user_id, transactions.user_id, profiles.user_id

   # Avoid: Inconsistent naming
   users.id, transactions.uid, profiles.customer_id
   ```

3. **Ensure that primary keys are unique and non-null.**
   Each primary key must identify exactly one row.

   ```python
   # Validate uniqueness
   assert df['user_id'].nunique() == len(df)
   assert df['user_id'].notna().all()
   # Stop and correct invalid keys before graph construction.
   ```

## Plan Semantic Types

A Kumo semantic type describes how Kumo should interpret a column, independently of how pandas stores it.
Before constructing the graph, plan the semantic type for each important column:

* Identifiers and relationship keys must use `ID`.
* Free-form descriptions must use `text`.
* Labels from a finite set must use `categorical`.
* Quantities and measurements must use `numerical`.
* Event times must use `timestamp`.

After creating the graph, review the inferred semantic types and correct any that do not match the column's role.

## Plan Prediction-Ready Relationships

Plan for the Predictive Query Language (PQL) questions that you want to ask when you prepare your source tables.
For example, predicting future transaction activity for each user requires an entity table for users, a timestamped event table for transactions, and a key that relates each transaction to a user.

## Common Data Modeling Patterns

The following patterns show how to separate common business data into tables with clear keys and relationships.

### Entity-event pattern

Use this pattern when one table describes entities and another records events associated with them.

```python
# Users (entity) with transactions (events)
users = pd.DataFrame({'user_id': [1, 2], 'name': ['Alice', 'Bob']})
transactions = pd.DataFrame({
    'transaction_id': [1, 2, 3],
    'user_id': [1, 1, 2],
    'amount': [100, 50, 200],
    'timestamp': ['2023-01-01', '2023-01-02', '2023-01-03']
})
```

### Hierarchical entities

Use this pattern when entities belong to other entities at multiple levels.

```python
# Multiple levels: company -> department -> employee
companies = pd.DataFrame({'company_id': [1, 2], 'company_name': ['ACME', 'TechCorp']})
departments = pd.DataFrame({'dept_id': [1, 2], 'company_id': [1, 1], 'dept_name': ['Engineering', 'Sales']})
employees = pd.DataFrame({'emp_id': [1, 2, 3], 'dept_id': [1, 1, 2], 'emp_name': ['Alice', 'Bob', 'Charlie']})
```

### Junction table for a many-to-many relationship

Use this pattern when each record in either entity table can relate to multiple records in the other.

```python
# Products and categories with many-to-many relationship
products = pd.DataFrame({'product_id': [1, 2], 'product_name': ['Laptop', 'Mouse']})
categories = pd.DataFrame({'category_id': [1, 2], 'category_name': ['Electronics', 'Accessories']})
product_categories = pd.DataFrame({
    'product_category_id': [1, 2, 3],
    'product_id': [1, 1, 2],
    'category_id': [1, 2, 2]
})
```

## Next Step

After choosing a table design and preparing your data, continue with
[Create a Graph](/kumo-relational/user-guide/build-a-relational-graph/graph-creation).
Use [Data Requirements](/kumo-relational/user-guide/prepare-data/data-requirements)
to check required keys, types, and timestamps.