This repository has been archived by the owner on Feb 22, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRObject.mjs
133 lines (114 loc) · 2.98 KB
/
RObject.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
"use strict";
// import ref from "ref";
// import refArray from "ref-array";
// import R from "./R";
// import {REALSXP} from "./libR";
// import SEXPWrap from "./SEXPWrap";
import debug_ from "debug";
const debug = debug_("libr-bridge:RObject");
/**
* JavaScript class for R Array type.
* Please use appropriate deriverd class if possible.
*/
export class RArray extends Array{
// nothing special. It's only an alias.
}
export class RIntArray extends RArray{
}
export class RBoolArray extends RArray{
}
export class RStrArray extends RArray{
}
export class RRealArray extends RArray{
}
export class RComplexArray extends RArray{
}
/**
* JavaScript class for R Factor type.
* A factor has numerical(integer) array with keys.
*/
export class RFactor extends RArray{
/**
* Create a factor.
* @param data {string[]} String array indicate category, like ["male", "female", "male", ...]
* @param levels {Object} Category item like ["male", "female"]
* @param ordered {boolean} If true, this factor is ordered factor (nominal)
*/
constructor(data, levels=undefined, ordered=false){
var mylevels;
if(!Array.isArray(data)){
super(data);
}else{
if(levels === undefined){
var s = new Set();
data.forEach((item) => s.add(item));
mylevels = Array.from(s);
}else if(Array.isArray(levels)){
mylevels = levels;
}else{
throw new Error("Unknown label of factor.");
}
mylevels = mylevels.filter((v) => v !== undefined);
// RFactor is 1-origin!
const values = data.map((v) => mylevels.indexOf(v) + 1)
.map((v) => v === 0 ? undefined : v);
super(...values);
}
this.levels = mylevels;
this.ordered = ordered;
}
/**
* Return proxy object which returns factor in String.
*/
asString(){
return new Proxy(this, {
get: (target, prop, receiver) => {
if(typeof(prop) === "string" && Number(prop) === prop * 1 ){
const i = target[prop];
return i ? this.levels[i - 1] : undefined;
}else if (prop === "Unproxy"){
return target;
}else{
return Reflect.get(target, prop, receiver);
}
}
});
}
}
/**
* JavaScript class for R Data Frame type.
* With a data frame, we can perform data analysis.
*/
export class RDataFrame extends Map{
/**
* Create RDataFrame from object.
* e.g.:
* {
* "id": [ 12345, 23456, 34567 ],
* "Name": ["apple", "banana", "orange"],
* "Color": ["red", "yellow", "orange"]
* }
* or, use Map.
* Please take care that all items in the data frame have same number of items.
*/
constructor(data){
console.assert(typeof(data) === "object");
if(!(data instanceof Map)){
// Object -> Map
data = new Map(Object.entries(data));
}
// check if all members have same length.
let length_of_item = [];
for(const item in data){
length_of_item.push(data[item].length);
}
if(length_of_item.some((n) => n !== length_of_item[0])){
console.log(length_of_item);
throw new Error("Vector size mismatch.");
}
super(data);
}
}
/*
* vim: filetype=javascript
*/