PyRlang
R-style syntax, running on pure Python. No R runtime, no compilation, zero dependencies.
PyRlang lets you write R the way R programmers actually type it — x <- c(1, 2), 1:10, df$col,
%>%, %in%, y ~ x — and runs it as ordinary Python underneath. It also ships the R-flavoured
data types as a normal Python library, usable from plain .py files.
- PyPI distribution name:
pyr4py(PyPI compares names with-/_stripped, so the whole family is blocked:pyris a 2013 REPL,pyrlangis an actively developed BEAM runtime, and thereforepyr-lang/PyRlangare rejected on upload too.pyr4py— "PyR for Python" — is the distribution name) - Import name:
PyRlang(import PyRlang,from PyRlang import *) - License: GPL-3.0-or-later
- Python: >= 3.10
Install
pip install pyr4py
Two ways to use it
1. R-style scripts (.pyr) — full syntax
Write hello.pyr:
x <- c(2, 4.5, 8, 1, 3.3, NA)
mean(x, na.rm = TRUE)
summary(x)
v <- 1:5
v[1] # one-based: the FIRST element
v[-1] # drops the first element, R-style
df <- data.frame(
name = c("ada", "bob"),
age = c(34, 47)
)
df$age
df[df$age > 35, ]
df$senior <- df$age > 40
df$age %>% mean() %>% round(2)
10 %in% c(4, 8, 10)
paste("R", "on", "Python", sep = "-") |> toupper()
f <- wage ~ age
Run it like an R script:
PyRlang hello.pyr # or: python -m PyRlang hello.pyr
Top-level expressions echo their results exactly like the R console,
vectors print as [1] 2 4.5 8 1 3.3 NA.
2. Interactive REPL
$ PyRlang
PyRlang 0.1.0 on Python 3.12 — R-style syntax, pure Python
Try: x <- c(1, 2, 3); mean(x). exit() or Ctrl-D to quit.
>> x <- c(1, 2, 3)
>> mean(x)
[1] 2
>> 1:5 %>% sum()
[1] 15
3. As a Python library
from PyRlang import *
v = c(1, 2, 3)
v[1] # 1 — one-based
mean(v) # 2.0
f = Formula("y ~ x")
df = data_frame(age=c(34, 47), wage=c(21.5, 33.0))
summary(df) # R-style six-number summaries
Syntax supported in transform mode
(.pyr files, the REPL, and PyRlang -e — plain .py files are never touched.)
| R syntax | becomes | notes |
|---|---|---|
x <- e |
x = e |
< and - must be adjacent, exactly like the real R parser |
x < -e |
unchanged | a space keeps it a Python comparison |
<<- |
not supported | clear error message |
a:b |
seq(a, b) |
outside []/{}; not after lambda, not annotations, not slices |
x ^ y |
x ** y |
|
x %% y |
x % y |
|
a && b |
a and b |
adjacent pair only, like R's scalar operators |
a || b |
a or b |
|
!x |
PyRlang.not_(x) |
element-wise negation — works on vectors |
a %in% b |
PyRlang.isin(a, b) |
vectorised membership |
a %>% f(b) |
PyRlang.pipe(a, f, b) |
magrittr; native R pipe a |> f(b) too |
y ~ x + z |
Formula('y ~ x + z') |
including inside call arguments: lm(y ~ x, data = d) style |
df$col |
df.col |
|
data.frame(…) |
DataFrame(…) |
also read.csv, write.csv, which.max, which.min, na.rm=, length.out= |
Semantics, by design
- One-based indexing.
v[1]is the first element; index 0 is an error with an R-style message.v[2:4]returns elements 2, 3, 4 (inclusive, like R), and out-of-range slices pad withNA. - Negative subscripts drop elements.
v[-1]removes the first element. (This differs deliberately from Python's negative indexing.) - Recycling.
c(1, 2) + c(1, 2, 3, 4)recycles the shorter vector, like R. - NA everywhere. A real
NAsentinel:NA + 1isNA,mean(c(1, NA))isNAunless you writena.rm = TRUE,if (NA)raises R's error message. - R-flavoured printing. Vectors print as
[1] 1 2 3, strings quoted, logicals asTRUE/FALSE, six-number summaries in R's column layout. - Division by zero is
Inf/NaN, not an exception — like R.
What ships in the library
- Constructors/inspection:
c,seq,rep,length,unique,sort,rev,head,tail,which,which.max,which.min,table - Statistics:
mean,median,sd,var,min,max,sum,prod,summary,sqrt,exp,log, all NA-aware - Strings:
paste,paste0,sprintf,nchar,toupper,tolower,substr,substring,cat - Data:
data.frame,$, R-style row/column subsetting,nrow,ncol,names,read.csv,write.csv - Logic:
ifelse,%in%, element-wise&,|,!, vectorised comparisons
Honest limitations (v0.1)
- No R block syntax (
for (i in 1:10) { ... }) — keep Python blocks, use R expressions inside them. ->(right assignment) is not yet transformed.lm,glm,plotand the modelling/graphics stack do not exist yet;Formulais data only.- No packages/namespaces; Python modules are imported normally.
- Type annotations in
.pyrfiles are not supported (R mode treatsn:mas a range). - Only Python >= 3.10 is supported.
Development
pip install -e ".[dev]"
pytest
ruff format . && ruff check .
python -m build
twine check dist/*
Run the examples:
python -m PyRlang examples/basics.pyr
python -m PyRlang examples/dataframe.pyr
PyRlang
Publishing to PyPI
The PyPI name for this project is pyr4py (taken-name note above).
python -m build
twine check dist/*
twine upload dist/pyr4py-0.1.0*
Use --repository testpypi to rehearse on TestPyPI, or configure an API token:
# ~/.pypirc
[pypi]
username = __token__
password = pypi-xxxxxxxx
License
GPL-3.0-or-later. See LICENSE.
Metadata
Release files for pyr4py 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pyr4py-0.1.1.tar.gz | 42.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyr4py-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 83.4 kB
Release files / pyr4py-0.1.1.tar.gz
| Download URL | pyr4py-0.1.1.tar.gz |
|---|---|
| Size | 42.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6135ac1b0e240b17bdf9182eb952d691cb431df2491727d20c8751bbdc8e3810
|
|
BLAKE2b-256 checksum How to use checksums |
1bc89b2acd38b9775ddfd40988c8c78538cd3acf3c882ff43f8ca8213b7cd1cb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|
Release files / pyr4py-0.1.1-py3-none-any.whl
| Download URL | pyr4py-0.1.1-py3-none-any.whl |
|---|---|
| Size | 41.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0c13e2439c0fff69d7d2d96f445d66e25afdc02462cabda8298b6fc5fe6ab7b5
|
|
BLAKE2b-256 checksum How to use checksums |
0f6bf0d72b3e843adb9b25b7187982572d5f2041a8582ef9dbe2848aa3eab824
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|
Security for pyr4py 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.