pyneatR 0.1.4
Neat formatting for numbers, dates, and strings using numpy.
License: MIT
Requires Python: >=3.9

# pyneatR

Neat formatting for numbers, dates, timestamps, and strings using numpy.
Implementation inspired by the R package [`neatR`](https://cran.r-project.org/web/packages/neatR/vignettes/neat-data.html).

## Installation

```bash
pip install pyneatR
```

## Neat Data for Presentation

### Formatting dates

Often, we encounter dates in various formats and want an unambiguous representation. `ndate` formats dates into a readable `mmm dd, yyyy` format with the day of the week.

```python
from pyneatR import ndate, nday
from datetime import date, timedelta

today = date.today()
# Assuming today is Nov 09, 2025 (Sun) for these examples

print(ndate(today - timedelta(days=3)))
# "Nov 06, 2025 (Thu)"

print(ndate(today))
# "Nov 09, 2025 (Sun)"

print(ndate(today + timedelta(days=4)))
# "Nov 13, 2025 (Thu)"
```

To just get the date without the day of week, set `show_weekday=False`:

```python
print(ndate(today, show_weekday=False))
# "Nov 09, 2025"
```

For monthly data, abbreviating the date to `mmm'yy` is elegant:

```python
print(ndate(today, show_weekday=False, show_month_year=True))
# "Nov'25"
```

To see the context of the date with respect to current date (within 1 week), use `nday`.

```python
print(nday(today, show_relative_day=False))
# "Sun"

```python
print(nday(today, show_relative_day=True))
# "Today, Sun"
```

### Formatting timestamp

Timestamps are feature-rich representations of date and time.

```python
from pyneatR import ntimestamp
from datetime import datetime

now = datetime.now()
# Assuming now is Nov 09, 2025 12:07:48 PM

print(ntimestamp(now))
# "Nov 09, 2025 12H 07M 48S PM (Sun)"
```

To extract and format only the time:

```python
print(ntimestamp(now, show_weekday=False, show_date=False, show_timezone=False))
# "12H 07M 48S PM"
```

Components of time can be toggled on or off:

```python
print(ntimestamp(now, show_date=False, show_weekday=False, 
                 show_hours=True, show_minutes=True, show_seconds=False, 
                 show_timezone=False))
# "12H 07M PM"
```

### Formatting number

`nnumber` formats numeric data in a readable way, automatically handling large numbers.

```python
from pyneatR import nnumber
import numpy as np

x = np.array([10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000])

print(nnumber(x))
# ['10.0' '100.0' '1.0 K' '10.0 K' '100.0 K' '1.0 Mn' '10.0 Mn' '100.0 Mn' '1.0 Bn']

print(nnumber(x, digits=0))
# ['10' '100' '1 K' '10 K' '100 K' '1 Mn' '10 Mn' '100 Mn' '1 Bn']
```

`nnumber` can automatically determine the best single unit for all numbers using `unit='auto'`:

```python
x = np.array([1e6, 99e3, 76e3, 42e3, 12e3, 789, 53])
print(nnumber(x, unit='auto'))
# ['1,000 K' '99 K' '76 K' '42 K' '12 K' '0.8 K' '0.1 K']
```

You can specify the unit directly:

```python
print(nnumber(123456789.123456, unit='Mn'))
# "123.5 Mn"
```

Default units are 'K', 'Mn', 'Bn', 'Tn'. Custom labels can be provided:

```python
print(nnumber(123456789.123456, unit='M', unit_labels={'million': 'M'}))
# "123.5 M"
```

Prefixes and suffixes can be added:

```python
print(nnumber(123456789.123456, unit='Mn', prefix='$ '))
# "$ 123.5 Mn"
```

To show the raw number with separators:

```python
print(nnumber(123456789.123456, digits=2, unit='', thousand_separator=','))
# "123,456,789.12"
```

### Formatting percentages

`npercent` formats percentages, handling both decimals (0.228) and values already multiplied by 100 (22.8).

```python
from pyneatR import npercent

print(npercent(22.8, is_ratio=False))
# "+22.8%"

print(npercent(0.228, is_ratio=True))
# "+22.8%"
```

By default `is_ratio=True`. The plus sign can be toggled:

```python
print(npercent(0.228, show_plus_sign=False))
# "22.8%"
```

For growth factors:

```python
tesla_2017 = 20
tesla_2023 = 200
g = (tesla_2023 - tesla_2017) / tesla_2017

print(npercent(g, show_plus_sign=True, show_growth_factor=True))
# "+900.0% (9.0x Growth)"
```

### Formatting string

`nstring` formats character vectors, removing special characters or changing case.

```python
from pyneatR import nstring

s = ' All MOdels are wrong. some ARE useful!!! '
print(nstring(s, case='title', remove_specials=True))
# "All Models Are Wrong Some Are Useful"
```

To retain only English alphabets and numbers:

```python
print(nstring(s, case='title', remove_specials=True, ascii_only=True))
# "All Models Are Wrong Some Are Useful"
```

### Smart Formatting with `f`

The `f` function is a "smart" formatter that infers the input type and applies the most appropriate `pyneatR` formatting with standardized defaults.

```python
from pyneatR import f
from datetime import date, datetime

# Infers Date
print(f(date(2026, 1, 1)))
# "Jan 01, 2026"

# Infers Timestamp (with IST and Weekday)
print(f(datetime(2025, 11, 9, 12, 7, 48)))
# "Nov 09, 2025 12H 07M 48S PM IST (Sun)"

# Infers Number (with scaling and separators)
print(f(1345000000000))
# "1.3 Tn"

# Infers Percent (with growth factor and bps)
print(f(9.0, format_type='percent'))
# "+900.0% (9x growth, 90K basis points)"

# Infers String (Title Case + Cleaning)
print(f("all Models are Wrong!!!"))
# "All Models Are Wrong"
```

You can explicitly set `format_type` if inference isn't what you want: `day`, `date`, `ts`, `number`, `percent`, `string`. All standard parameters can be passed via `**kwargs`.