{"id":18075737,"url":"https://github.com/leafyeexyz/psychlib","last_synced_at":"2025-09-08T00:33:05.088Z","repository":{"id":268799905,"uuid":"882886648","full_name":"LeafYeeXYZ/PsychLib","owner":"LeafYeeXYZ","description":"A JavaScript/TypeScript library for math, statistics, and data analysis. Featured in psychological and educational research.","archived":false,"fork":false,"pushed_at":"2025-07-09T04:08:30.000Z","size":674,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-09T05:21:32.403Z","etag":null,"topics":["beijing-normal-university","bnu","deno","education","javascript","jsr","math","psychology","statistics","typescript"],"latest_commit_sha":null,"homepage":"https://jsr.io/@psych/lib","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LeafYeeXYZ.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-11-04T01:30:54.000Z","updated_at":"2025-07-09T04:08:34.000Z","dependencies_parsed_at":"2024-12-19T02:24:01.320Z","dependency_job_id":"e05e1005-6914-460d-bc1c-ce11e37ed2ce","html_url":"https://github.com/LeafYeeXYZ/PsychLib","commit_stats":null,"previous_names":["leafyeexyz/psychlib"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/LeafYeeXYZ/PsychLib","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeafYeeXYZ%2FPsychLib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeafYeeXYZ%2FPsychLib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeafYeeXYZ%2FPsychLib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeafYeeXYZ%2FPsychLib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LeafYeeXYZ","download_url":"https://codeload.github.com/LeafYeeXYZ/PsychLib/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeafYeeXYZ%2FPsychLib/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274117170,"owners_count":25225100,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-07T02:00:09.463Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["beijing-normal-university","bnu","deno","education","javascript","jsr","math","psychology","statistics","typescript"],"created_at":"2024-10-31T11:07:07.111Z","updated_at":"2025-09-08T00:33:05.076Z","avatar_url":"https://github.com/LeafYeeXYZ.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Introduction\n\n[![JSR Version](https://jsr.io/badges/@psych/lib)](https://jsr.io/@psych/lib) [![JSR Scope](https://jsr.io/badges/@psych)](https://jsr.io/@psych) [![JSR Score](https://jsr.io/badges/@psych/lib/score)](https://jsr.io/@psych/lib/score)\n\n**PsychLib** is a TypeScript library for math, statistics, and data analysis. Featured in psychological and educational research.\n\n- PsychLib can be used in all modern JavaScript/TypeScript environments, including browsers, Node.js, Deno, and Bun.\n- For use cases, please refer to my another project [PsychPen](https://github.com/LeafYeeXYZ/PsychPen).\n- All functions have been tested for consistency with R's psych package and other JavaScript/R statistical libraries.\n\n**For full documentation, see \u003chttps://jsr.io/@psych/lib/doc\u003e.**\n\n- [Introduction](#introduction)\n- [Qiuck Start](#qiuck-start)\n- [Development](#development)\n- [Testing](#testing)\n- [Benchmark](#benchmark)\n\n# Qiuck Start\n\n```bash\nnpx jsr add @psych/lib # if using npm\nbunx jsr add @psych/lib # if using bun\ndeno add jsr:@psych/lib # if using deno\npnpm dlx jsr add @psych/lib # if using pnpm\nyarn dlx jsr add @psych/lib # if using yarn\n```\n\n```typescript\nimport { randomNormal, WelchTTest } from '@psych/lib'\n\nconst groupA = new Array(500).fill(0).map(() =\u003e randomNormal(10, 2))\nconst groupB = new Array(500).fill(0).map(() =\u003e randomNormal(11, 2))\nconst tTest = new WelchTTest(groupA, groupB)\nconsole.log(tTest.t, tTest.df, tTest.p) // Maybe -6.5..., 997.4..., 0.0...\n```\n\n**For full documentation, see \u003chttps://jsr.io/@psych/lib/doc\u003e.**\n\n# Development\n\nIf you haven't installed `deno` yet, please install it referring to the \u003chttps://deno.com\u003e. Then, clone this repository.\n\n```bash\ngit clone https://github.com/LeafYeeXYZ/PsychLib.git\n```\n\nNow you can write `TypeScript` code in `/lib/**/*.ts` and export functions in `/lib/index.ts`. Note that you should not import base functions from `/lib/index.ts` to avoid circular dependencies. Instead, you can import them directly from `/lib/base.ts` or `/lib/xxx/index.ts`.\n\nAfter writing the code, remember to add test cases in `/tests/*.test.ts`. You can run the test cases using the following command.\n\n```bash\ndeno task r:install # only once\ndeno task r:server\ndeno task test\n```\n\nYou can also add benchmark cases in `/benchs/*.bench.ts` and run the benchmark using the following command.\n\n```bash\ndeno task bench\n```\n\nThis project publishes to \u003chttps://jsr.io\u003e, so you don't need to compile the code to JavaScript. And you also don't need to publish the package manually. Just modify `deno.json` and push the code to the repository. The `GitHub Action` will do the rest for you.\n\n# Testing\n\n| PsychLib Function | Testing Method | Passed | Precision | Note |\n| :---: | :---: | :---: | :---: | :---: |\n| Basic Functions | `JS:simple-statistics` | 🟩 | `1e-6` | |\n| `Matrix` | `JS:ml-matrix` | 🟩 | `1e-6` | |\n| `sort` | `JS:Array.prototype.sort` | 🟩 | `0` | |\n| `OneSampleTTest` | `R:psych` | 🟩 | `1e-4` | |\n| `TwoSampleTTest` | `R:psych` | 🟩 | `1e-4` | |\n| `PeerSampleTTest` | `R:psych` | 🟩 | `1e-4` | |\n| `WelchTTest` | `R:psych` | 🟩 | `1e-4` | |\n| `AlphaRealiability` | `R:psych` | 🟩 | `1e-4` | |\n| `LeveneTest` | `R:car` | 🟩 | `1e-4` | |\n| `OneSampleKSTest` | `R:stats` | 🟨 | `1e-4` | the precision for `p` when `n \u003c 100` is worse than `1e-4` |\n| `z2p` \u0026 `p2z` | `R:stats` | 🟩 | `1e-4` | |\n| `t2p` \u0026 `p2t` | `R:stats` | 🟩 | `1e-4` | |\n| `f2p` \u0026 `p2f` | `R:stats` | 🟩 | `1e-4` | |\n| `c2p` \u0026 `p2c` | `R:stats` | 🟩 | `1e-4` | |\n| `PearsonCorrTest` | `R:stats` | 🟩 | `1e-4` | |\n| `OneWayAnova` | `R:stats` | 🟩 | `1e-4` | |\n| `PeerAnova` | `R:stats` | 🟩 | `1e-4` | |\n| ANOVA Post Hoc | see `tests/anova.test.ts` | 🟥 WIP | |\n| Regression | See `tests/regression.test.ts` | 🟥 WIP | |\n| Mediation | `R:lavaan` | 🟩 | `1e-4` | `p` value is not tested |\n\n\u003e I'm working on migrating all tests to `R`, you can see the progress above.\n\n# Benchmark\n\n```bash\n    CPU | Apple M3\nRuntime | Deno 2.4.1 (aarch64-apple-darwin)\n   File | /benchs/base.bench.ts\n\n\n| benchmark                             | time/iter (avg) |        iter/s |      (min … max)      |      p75 |      p99 |     p995 |\n| ------------------------------------- | --------------- | ------------- | --------------------- | -------- | -------- | -------- |\n| sum() - n=1000                        |          1.0 µs |       979,400 | (583.0 ns …  53.5 µs) |   1.3 µs |   1.6 µs |   1.6 µs |\n| mean() - n=1000                       |          1.3 µs |       748,500 | (625.0 ns …  34.0 µs) |   1.4 µs |   1.6 µs |   1.6 µs |\n| max() - n=1000                        |        442.0 ns |     2,262,000 | (333.0 ns …  39.5 µs) | 458.0 ns | 708.0 ns | 709.0 ns |\n| min() - n=1000                        |          1.1 µs |       917,400 | (375.0 ns …  39.4 µs) |   1.2 µs |   1.5 µs |   1.5 µs |\n| median() - n=1000                     |         41.9 µs |        23,880 | ( 36.8 µs …  92.1 µs) |  42.4 µs |  49.5 µs |  51.6 µs |\n| mode() - n=1000                       |         82.2 µs |        12,160 | ( 72.2 µs … 169.5 µs) |  82.2 µs | 123.6 µs | 135.0 µs |\n| quantile() - n=1000                   |         41.9 µs |        23,890 | ( 36.9 µs …  77.1 µs) |  42.5 µs |  49.5 µs |  51.2 µs |\n| range() - n=1000                      |          1.4 µs |       697,400 | (834.0 ns …  31.0 µs) |   1.5 µs |   1.8 µs |   1.8 µs |\n| vari() - n=1000                       |          3.0 µs |       332,600 | (  1.4 µs …  62.5 µs) |   3.0 µs |   3.6 µs |   3.8 µs |\n| std() - n=1000                        |          1.4 µs |       709,200 | (  1.2 µs …  30.0 µs) |   1.4 µs |   1.8 µs |   3.0 µs |\n| cov() - n=1000                        |          2.1 µs |       473,900 | (  1.9 µs …  16.1 µs) |   2.1 µs |   2.6 µs |   2.7 µs |\n| corr() - n=1000                       |          6.8 µs |       147,000 | (  3.4 µs …  97.5 µs) |   7.3 µs |   8.2 µs |   8.9 µs |\n| kurtosis() - n=1000                   |         13.3 µs |        74,960 | ( 11.7 µs …   4.7 ms) |  12.6 µs |  30.0 µs |  30.1 µs |\n| skewness() - n=1000                   |         12.5 µs |        79,780 | ( 11.7 µs …  76.9 µs) |  12.5 µs |  15.4 µs |  18.4 µs |\n| ss() - n=1000                         |          2.0 µs |       506,100 | (  1.3 µs …  22.4 µs) |   2.9 µs |   3.0 µs |   3.2 µs |\n| ssDiff() - n=1000                     |          1.9 µs |       525,200 | (708.0 ns …  49.3 µs) |   2.1 µs |   2.3 µs |   2.5 µs |\n| sem() - n=1000                        |          1.4 µs |       702,700 | (  1.3 µs …   9.9 µs) |   1.5 µs |   1.8 µs |   1.8 µs |\n| array.sort() - n=1000                 |        260.5 µs |         3,839 | (243.0 µs …   1.0 ms) | 262.5 µs | 314.6 µs | 334.9 µs |\n| array.toSorted() - n=1000             |        127.6 µs |         7,839 | (118.6 µs … 551.9 µs) | 126.6 µs | 164.4 µs | 217.9 µs |\n| sort() - quickSort (iter) - n=1000    |         45.6 µs |        21,910 | ( 40.5 µs … 261.1 µs) |  45.9 µs |  54.0 µs |  56.0 µs |\n| sort() - quickSort (recur) - n=1000   |         50.3 µs |        19,870 | ( 44.5 µs … 160.5 µs) |  50.8 µs |  55.7 µs |  57.7 µs |\n| sort() - mergeSort - n=1000           |         73.0 µs |        13,690 | ( 70.8 µs … 477.7 µs) |  72.9 µs |  80.8 µs |  86.9 µs |\n| sort() - heapSort - n=1000            |         91.6 µs |        10,910 | ( 88.2 µs … 287.5 µs) |  91.3 µs | 106.0 µs | 112.3 µs |\n| z2p()                                 |          4.2 ns |   239,700,000 | (  3.7 ns …   1.1 µs) |   3.9 ns |   9.0 ns |   9.9 ns |\n| p2z()                                 |         14.6 ns |    68,410,000 | ( 13.8 ns …  31.4 ns) |  14.6 ns |  19.5 ns |  22.0 ns |\n| t2p() - df=30                         |        116.0 ns |     8,623,000 | (112.8 ns … 139.1 ns) | 116.3 ns | 127.3 ns | 128.8 ns |\n| p2t() - df=30                         |        556.9 ns |     1,796,000 | (550.7 ns … 584.7 ns) | 558.3 ns | 575.0 ns | 584.7 ns |\n| f2p() - df=5,30                       |         93.7 ns |    10,680,000 | ( 92.6 ns … 106.8 ns) |  93.7 ns | 100.3 ns | 101.7 ns |\n| p2f() - df=5,30                       |        565.3 ns |     1,769,000 | (550.6 ns … 593.1 ns) | 568.1 ns | 593.1 ns | 593.1 ns |\n| c2p() - df=5                          |         46.4 ns |    21,560,000 | ( 45.7 ns …  59.1 ns) |  46.5 ns |  48.3 ns |  50.0 ns |\n| p2c() - df=5                          |        345.1 ns |     2,898,000 | (325.0 ns … 361.2 ns) | 347.4 ns | 357.4 ns | 361.2 ns |\n| randomNormal()                        |         15.6 ns |    64,020,000 | ( 14.5 ns …  29.1 ns) |  15.7 ns |  18.4 ns |  20.0 ns |\n| randomT() - df=30                     |         73.1 ns |    13,690,000 | ( 70.5 ns …  87.6 ns) |  73.6 ns |  80.2 ns |  82.8 ns |\n| randomF() - df=5,30                   |        113.3 ns |     8,829,000 | (108.8 ns … 128.1 ns) | 114.4 ns | 124.8 ns | 127.2 ns |\n| randomChi2() - df=5                   |         54.9 ns |    18,220,000 | ( 52.6 ns …  66.4 ns) |  55.2 ns |  59.5 ns |  61.5 ns |\n| matrix.add() - 50x50                  |         12.1 µs |        82,710 | ( 11.3 µs … 176.0 µs) |  12.0 µs |  16.5 µs |  34.4 µs |\n| matrix.transpose() - 50x50            |         11.0 µs |        91,160 | ( 10.4 µs … 165.0 µs) |  11.0 µs |  12.5 µs |  13.9 µs |\n| matrix.multiply() - 50x50             |        378.5 µs |         2,642 | (339.8 µs …   2.9 ms) | 348.0 µs | 498.0 µs |   1.6 ms |\n| matrix.inverse() - 50x50              |        472.6 µs |         2,116 | (449.1 µs …   5.6 ms) | 457.1 µs | 779.0 µs | 994.7 µs |\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleafyeexyz%2Fpsychlib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleafyeexyz%2Fpsychlib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleafyeexyz%2Fpsychlib/lists"}