Skip to content

Commit

Permalink
Merge pull request #25 from statisticsnorway/pep8
Browse files Browse the repository at this point in the history
Rename functions and variables to PEP8 standard
  • Loading branch information
Kss2k authored Oct 27, 2024
2 parents ed2b472 + e8618ed commit 5047025
Show file tree
Hide file tree
Showing 31 changed files with 701 additions and 696 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@ dt = wr.library("datasets")
dplyr.last(x=np.array([1, 2, 3, 4]))
dplyr.last(x=[1, 2, 3, 4])


iris = dt.iris
df = dplyr.mutate(iris, Sepal = wr.lazily("round(Sepal.Length * 2, 0)"))
df = dplyr.mutate(iris, Sepal=wr.Lazily("round(Sepal.Length * 2, 0)"))
```

## To do
Expand Down
964 changes: 486 additions & 478 deletions poetry.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/rwrapr/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

warnings.simplefilter("always")

from .lazy_rexpr import lazily
from .lazy_rexpr import Lazily
from .library import importr
from .library import library
from .load_namespace import try_load_namespace
Expand All @@ -31,7 +31,7 @@
"Renv",
"Settings",
"importr",
"lazily",
"Lazily",
"library",
"settings",
"try_load_namespace",
Expand Down
3 changes: 1 addition & 2 deletions src/rwrapr/convert_py2r.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
# We can uncomment this when we transition to 3.12
RBaseObject: TypeAlias = (
ro.FloatVector
| ro.FloatVector
| ro.IntVector
| ro.ListVector
| ro.Array
Expand Down Expand Up @@ -50,7 +49,7 @@ def convert_py2r(x: Any) -> RBaseObject | PyDtype | Any:

match x:
case RView() | RArray() | RList() | RDataFrame() | RDict() | RFactor():
return x.toR()
return x.to_r()
case _ if x is np.nan:
return (
ro.NA_Logical
Expand Down
14 changes: 7 additions & 7 deletions src/rwrapr/convert_r2py.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import rpy2.rlike.container as rcnt
import rpy2.robjects as ro
import rpy2.robjects.vectors as vc
from rpy2.robjects import rpy2
from rpy2.rinterface_lib.sexp import NULLType

from .rdataframe import RDataFrame
from .rdataframe import attempt_pandas_conversion
Expand All @@ -21,16 +21,16 @@


# TODO: Consider changing return type hint to union of possible types
def convert_r2py(x: Any, ignoreS3: bool = False) -> Any:
def convert_r2py(x: Any, ignore_s3: bool = False) -> Any:
# Need to import these here to avoid circular imports
from .rarray import filter_numpy
from .rarray import get_RArray
from .rarray import get_rarray
from .rarray import is_valid_numpy

match x:
case str() | int() | bool() | float():
return x
case rpy2.rinterface_lib.sexp.NULLType():
case NULLType():
return None
case _ if is_na(x):
return (
Expand All @@ -41,17 +41,17 @@ def convert_r2py(x: Any, ignoreS3: bool = False) -> Any:
case vc.FactorVector():
return RFactor(x)
case vc.Vector() | vc.Matrix() | vc.Array() if not is_rlist(x):
return get_RArray(x) # return RArray, or int|str|bool|float if len == 1
return get_rarray(x) # return RArray, or int|str|bool|float if len == 1
case ro.methods.RS4():
return convert_s4(x)
case _ if has_unsupported_rclass(x) and not ignoreS3:
case _ if has_unsupported_rclass(x) and not ignore_s3:
return RView(x)
case list():
return convert_r2pylist(x)
case tuple():
return convert_r2pylist(x)
case rcnt.OrdDict():
return convert_r2pydict(x, is_RDict=True)
return convert_r2pydict(x, is_rdict=True)
case dict():
return convert_r2pydict(x)
case pd.DataFrame():
Expand Down
2 changes: 1 addition & 1 deletion src/rwrapr/function_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def wrap(*args: Any, **kwargs: Any) -> RReturnType:
convert_py_args2r(args=args, kwargs=kwargs) # type: ignore[arg-type]
lazyfunc = lazy_wrap(args=args, kwargs=kwargs, func=func, func_name=name) # type: ignore[arg-type]
r_object: Any = lazyfunc(*args, **kwargs)
if settings.Rview:
if settings.rview_mode:
return RView(r_object)
else:
return convert_r2py(r_object)
Expand Down
6 changes: 3 additions & 3 deletions src/rwrapr/lazy_rexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from .rutils import rcall


class lazily:
class Lazily:
def __init__(self, expr: str) -> None:
if not isinstance(expr, str):
raise TypeError("lazy-expr must be in the form of a string")
Expand All @@ -25,12 +25,12 @@ def lazy_wrap(
) -> Callable[..., Any] | Any:
lazy_arg_exprs: list[str] = []
for x in args:
if isinstance(x, lazily):
if isinstance(x, Lazily):
raise TypeError(
f"Lazy argument needs to be a keyword argument, {x} is unnamed"
)
for k, v in kwargs.copy().items():
if isinstance(v, lazily):
if isinstance(v, Lazily):
lazy_arg_exprs.append(f"{k} = {v!s}")
del kwargs[k]

Expand Down
4 changes: 2 additions & 2 deletions src/rwrapr/load_namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ def load_base_envs() -> (
):
# set options for global environment
rbase = try_load_namespace("base", verbose=False)
rMatrix = try_load_namespace("Matrix", verbose=False)
rmatrix = try_load_namespace("Matrix", verbose=False)
rutils = try_load_namespace("utils", verbose=False)
return {"base": rbase, "Matrix": rMatrix, "utils": rutils}
return {"base": rbase, "Matrix": rmatrix, "utils": rutils}


def try_load_namespace(
Expand Down
60 changes: 31 additions & 29 deletions src/rwrapr/rarray.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import warnings
from collections.abc import Callable
from typing import Any
Expand All @@ -10,31 +12,31 @@
from rpy2.rinterface_lib.sexp import NULLType

from .convert_py2r import convert_py2r
from .rattributes import get_Rattributes
from .rattributes import get_rattributes
from .toggle_rview import ToggleRView


NPArrayIndex: TypeAlias = tuple[slice | int | list[Any] | NDArray[Any], ...]


class RArray(np.ndarray[Any, Any]):
def __new__(cls, Rdata: Any) -> "RArray":
arr = convert_numpy(Rdata)
def __new__(cls, rdata: Any) -> RArray:
arr = convert_numpy(rdata)
if not isinstance(arr, np.ndarray):
raise TypeError("convert_numpy(Rdata) must return a numpy.ndarray")

# Ensure the array is in C order
arr_c = np.ascontiguousarray(arr)
obj = arr_c.view(cls)

obj._Rattributes = get_attributes_array(Rdata)
obj._rattributes = get_attributes_array(rdata)
return obj

def __array_finalize__(self, obj: Any) -> None:
if obj is None:
return
# Copy the _Rattributes from the source object
self._Rattributes = getattr(obj, "_Rattributes", None)
# Copy the _rattributes from the source object
self._rattributes = getattr(obj, "_rattributes", None)

def __getitem__(self, index: Any) -> Any:
result = super().__getitem__(index)
Expand All @@ -43,13 +45,13 @@ def __getitem__(self, index: Any) -> Any:
if not isinstance(result, RArray):
return result

# Copy the _Rattributes
if hasattr(self, "_Rattributes") and self._Rattributes is not None:
result._Rattributes = getattr(self, "_Rattributes", {}).copy()
# Copy the _rattributes
if hasattr(self, "_rattributes") and self._rattributes is not None:
result._rattributes = getattr(self, "_rattributes", {}).copy()

orig_dimnames = self._Rattributes.get("dimnames", None)
orig_names = self._Rattributes.get("names", None)
orig_dim = self._Rattributes.get("dim", None)
orig_dimnames = self._rattributes.get("dimnames", None)
orig_names = self._rattributes.get("names", None)
orig_dim = self._rattributes.get("dim", None)

ndim_self = self.ndim
ndim_result = result.ndim
Expand Down Expand Up @@ -86,7 +88,7 @@ def __getitem__(self, index: Any) -> Any:
# Dimension is removed, do not add dimname
pass

result._Rattributes["dimnames"] = new_dimnames
result._rattributes["dimnames"] = new_dimnames

# Update names for 1D arrays
elif orig_names is not None:
Expand All @@ -100,18 +102,18 @@ def __getitem__(self, index: Any) -> Any:
indices = np.arange(len(names_array))[idx]
new_names = names_array[indices]

result._Rattributes["names"] = new_names
result._rattributes["names"] = new_names
elif ndim_self == 1 and ndim_result == 0:
result._Rattributes.pop("names", None)
result._rattributes.pop("names", None)

if orig_dim is not None:
if ndim_result > 0:
new_dim = result.shape
new_dim_array = np.array(new_dim)
result._Rattributes["dim"] = new_dim_array
result._rattributes["dim"] = new_dim_array
else:
# Result is scalar, remove 'dim' attribute
result._Rattributes.pop("dim", None)
result._rattributes.pop("dim", None)

return result

Expand Down Expand Up @@ -151,32 +153,32 @@ def _get_dims_kept(self, index_normalized: NPArrayIndex) -> list[bool]:
dims_kept.append(True)
return dims_kept

def toR(self) -> Any:
def to_r(self) -> Any:
from .rattributes import attributes2r
from .rattributes import structure

R_object = convert_numpy2r(np.asarray(self))
if self._Rattributes is not None:
R_attributes = attributes2r(self._Rattributes)
if R_attributes:
R_object = structure(R_object, **R_attributes)
R_object = structure(R_object, **R_attributes)
r_object = convert_numpy2r(np.asarray(self))
if self._rattributes is not None:
r_attributes = attributes2r(self._rattributes)
if r_attributes:
r_object = structure(r_object, **r_attributes)
r_object = structure(r_object, **r_attributes)

return R_object
return r_object

def toPy(self) -> NDArray[Any]:
def to_py(self) -> NDArray[Any]:
with ToggleRView(False):
out = np.asarray(self)
return out


def get_RArray(x: Any) -> RArray | bool | int | str | float:
def get_rarray(x: Any) -> RArray | bool | int | str | float:
y: RArray = RArray(x)
return y[0].item() if y.shape == (1,) and y._Rattributes is None else y
return y[0].item() if y.shape == (1,) and y._rattributes is None else y


def get_attributes_array(x: Any) -> dict[str, Any] | None | Any:
return get_Rattributes(x, exclude=["class"])
return get_rattributes(x, exclude=["class"])


def convert_numpy(
Expand Down
5 changes: 2 additions & 3 deletions src/rwrapr/rattributes.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from collections.abc import Callable
from typing import Any

from rwrapr.rlist import RDict

from .convert_py2r import convert_py_args2r
from .rlist import RDict


def get_Rattributes(x: Any, exclude: list[str] | None = None) -> Any:
def get_rattributes(x: Any, exclude: list[str] | None = None) -> Any:
from .function_wrapper import rfunc

if exclude is None:
Expand Down
22 changes: 11 additions & 11 deletions src/rwrapr/rdataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import rpy2.robjects.vectors as vc
from rpy2.robjects import pandas2ri

from .rattributes import get_Rattributes
from .rattributes import get_rattributes
from .toggle_rview import ToggleRView


Expand All @@ -22,29 +22,29 @@ def __init__(self, data_frame: vc.DataFrame | pd.DataFrame):

with warnings.catch_warnings():
warnings.simplefilter("ignore")
self._Rattributes = attrs
self._rattributes = attrs

def toR(self) -> vc.DataFrame:
def to_r(self) -> vc.DataFrame:
from .rattributes import attributes2r
from .rattributes import structure

R_df = pandas2r(self)
if self._Rattributes is None:
return R_df
r_df = pandas2r(self)
if self._rattributes is None:
return r_df
else:
attributes = attributes2r(self._Rattributes)
attributes = attributes2r(self._rattributes)
if not attributes:
return R_df
return structure(R_df, **attributes)
return r_df
return structure(r_df, **attributes)

def toPy(self) -> pd.DataFrame:
def to_py(self) -> pd.DataFrame:
with ToggleRView(False):
out = pd.DataFrame(self)
return out


def get_attributes_dataframe(df: vc.DataFrame) -> dict[str, Any] | None | Any:
return get_Rattributes(df, exclude=["names", "class", "row.names"])
return get_rattributes(df, exclude=["names", "class", "row.names"])


def pandas2r(df: pd.DataFrame) -> vc.DataFrame:
Expand Down
Loading

0 comments on commit 5047025

Please sign in to comment.