likingInitiative 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- likinginitiative-0.2.1/LICENSE +21 -0
- likinginitiative-0.2.1/PKG-INFO +156 -0
- likinginitiative-0.2.1/README.md +119 -0
- likinginitiative-0.2.1/pyproject.toml +64 -0
- likinginitiative-0.2.1/setup.cfg +4 -0
- likinginitiative-0.2.1/src/likingInitiative/__init__.py +60 -0
- likinginitiative-0.2.1/src/likingInitiative/catalog.py +61 -0
- likinginitiative-0.2.1/src/likingInitiative/citation.py +66 -0
- likinginitiative-0.2.1/src/likingInitiative/database.py +46 -0
- likinginitiative-0.2.1/src/likingInitiative/dataset.py +98 -0
- likinginitiative-0.2.1/src/likingInitiative/item.py +77 -0
- likinginitiative-0.2.1/src/likingInitiative/py.typed +0 -0
- likinginitiative-0.2.1/src/likingInitiative/release.py +258 -0
- likinginitiative-0.2.1/src/likingInitiative.egg-info/PKG-INFO +156 -0
- likinginitiative-0.2.1/src/likingInitiative.egg-info/SOURCES.txt +18 -0
- likinginitiative-0.2.1/src/likingInitiative.egg-info/dependency_links.txt +1 -0
- likinginitiative-0.2.1/src/likingInitiative.egg-info/requires.txt +9 -0
- likinginitiative-0.2.1/src/likingInitiative.egg-info/top_level.txt +1 -0
- likinginitiative-0.2.1/tests/test_likingInitiative.py +197 -0
- likinginitiative-0.2.1/tests/test_metadata.py +13 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Kianté Fernandez
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: likingInitiative
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: The Liking Rating Database in Python
|
|
5
|
+
Author: Kianté Fernandez
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/liking-initiative/likingInitiative-py
|
|
8
|
+
Project-URL: Source, https://github.com/liking-initiative/likingInitiative-py
|
|
9
|
+
Project-URL: Issues, https://github.com/liking-initiative/likingInitiative-py/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/liking-initiative/likingInitiative-py/blob/main/CHANGELOG.md
|
|
11
|
+
Project-URL: Data, https://doi.org/10.5281/zenodo.22216442
|
|
12
|
+
Keywords: psychology,decision-making,open-data,preference,liking
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.9
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: polars>=0.20
|
|
29
|
+
Requires-Dist: requests>=2.28
|
|
30
|
+
Requires-Dist: platformdirs>=3.0
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
33
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
34
|
+
Requires-Dist: build; extra == "dev"
|
|
35
|
+
Requires-Dist: twine; extra == "dev"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# likingInitiative — Python
|
|
39
|
+
|
|
40
|
+
[](https://github.com/liking-initiative/likingInitiative-py/actions/workflows/ci.yml)
|
|
41
|
+
[](https://doi.org/10.5281/zenodo.22216442)
|
|
42
|
+
|
|
43
|
+
The Liking Rating Database in Python: subjective liking ratings from
|
|
44
|
+
published decision-making studies, as [polars](https://pola.rs) frames.
|
|
45
|
+
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install git+https://github.com/liking-initiative/likingInitiative-py
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Requires Python 3.9 or newer. Data is downloaded from Zenodo on first use and
|
|
53
|
+
cached locally; no account or token is needed.
|
|
54
|
+
|
|
55
|
+
## Use
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
import likingInitiative
|
|
59
|
+
|
|
60
|
+
likingInitiative.list_datasets() # 59 datasets
|
|
61
|
+
likingInitiative.list_studies() # 38 studies
|
|
62
|
+
likingInitiative.list_items() # 2,217 stimuli
|
|
63
|
+
|
|
64
|
+
d = likingInitiative.get_dataset("leeholyoak2021")
|
|
65
|
+
d.data # polars DataFrame
|
|
66
|
+
d.scale # (1.0, 100.0)
|
|
67
|
+
d.timepoints # [1, 2, 3]
|
|
68
|
+
print(d.cite())
|
|
69
|
+
|
|
70
|
+
likingInitiative.get_dataset(["leeholyoak2021", "leehare2023exp2"]).data # stacked
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### One item across every study that used it
|
|
74
|
+
|
|
75
|
+
The cross-study view — the thing this database is built for:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
k = likingInitiative.get_item("kitkat") # 1,626 ratings across 25 datasets
|
|
79
|
+
k.by_dataset() # mean / sd / median per study, 0-1 scale
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### The whole corpus
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
db = likingInitiative.load_database()
|
|
86
|
+
db["ratings"] # 759,399 rows
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Two things to get right
|
|
90
|
+
|
|
91
|
+
**Cross-study comparisons must use `normalized_rating`.** Studies use
|
|
92
|
+
different response scales (0–4, 1–100, 1–870, willingness-to-pay in dollars),
|
|
93
|
+
so raw `rating` values are not comparable. `normalized_rating` is
|
|
94
|
+
`(rating − scale_min) / (scale_max − scale_min)` and always lies in 0–1.
|
|
95
|
+
|
|
96
|
+
**Subject ids are unique only within a dataset.** Subject `"12"` in two
|
|
97
|
+
datasets is two different people — key on `(dataset_code, subject_id)`.
|
|
98
|
+
|
|
99
|
+
## Repeated rating phases
|
|
100
|
+
|
|
101
|
+
Six datasets repeat the whole rating phase (`chenhol1`, `chenhol2`,
|
|
102
|
+
`crosswebb`, `hamesmcc`, `leehare2023exp2`, `leeholyoak2021`), so
|
|
103
|
+
`(subject_id, item_id)` alone is not unique for them:
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
d = likingInitiative.get_dataset("leeholyoak2021") # phases 1, 2, 3
|
|
107
|
+
d.data.group_by("timepoint").agg(pl.col("normalized_rating").mean())
|
|
108
|
+
|
|
109
|
+
likingInitiative.get_dataset("leeholyoak2021", timepoint=2) # one phase
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`get_item()` uses each dataset's first phase only, so a repeated-phase study
|
|
113
|
+
does not carry extra weight in a cross-study comparison.
|
|
114
|
+
|
|
115
|
+
## Versions and caching
|
|
116
|
+
|
|
117
|
+
Data comes from versioned release files, not a live service, so a pinned
|
|
118
|
+
version returns the same rows however long from now.
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
likingInitiative.release_info() # version, date, counts, migrations applied
|
|
122
|
+
likingInitiative.get_dataset("leeholyoak2021", version="1.6.2") # pin it
|
|
123
|
+
likingInitiative.cache_info(); likingInitiative.clear_cache()
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Set `LIKING_INITIATIVE_RELEASE_DIR` to a directory built by
|
|
127
|
+
`scripts/build_release.py` to work against an unreleased build.
|
|
128
|
+
|
|
129
|
+
## API
|
|
130
|
+
|
|
131
|
+
| Function | Returns |
|
|
132
|
+
|----------|---------|
|
|
133
|
+
| `list_studies()` / `list_datasets()` / `list_items()` | catalogue frames |
|
|
134
|
+
| `get_dataset(code, version, timepoint)` | `Dataset` — `.data`, `.metadata`, `.cite()` |
|
|
135
|
+
| `get_item(name, version)` | `Item` — `.data`, `.by_dataset()`, `.cite()` |
|
|
136
|
+
| `load_database(version)` | dict of frames |
|
|
137
|
+
| `cite(x)` / `bibtex(x)` | citation text |
|
|
138
|
+
| `release_info()` / `cache_info()` / `clear_cache()` | housekeeping |
|
|
139
|
+
|
|
140
|
+
## Citation
|
|
141
|
+
|
|
142
|
+
Please cite the database and the studies whose data you use. `cite()` with no
|
|
143
|
+
argument returns the database citation; `cite(d)` returns a study's.
|
|
144
|
+
|
|
145
|
+
> Fernandez, K., Goyal, S., & Krajbich, I. (2026). The Liking Initiative: a
|
|
146
|
+
> database of subjective evaluation ratings for decision-making research
|
|
147
|
+
> [Data set]. Zenodo. https://doi.org/10.5281/zenodo.22216442
|
|
148
|
+
|
|
149
|
+
That is the concept DOI, which always resolves to the newest version. To name
|
|
150
|
+
the exact bytes an analysis ran on, cite the version DOI that Zenodo lists for
|
|
151
|
+
the version `release_info()` reports.
|
|
152
|
+
|
|
153
|
+
## License
|
|
154
|
+
|
|
155
|
+
MIT. The underlying data remain subject to the terms of the original
|
|
156
|
+
publications.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# likingInitiative — Python
|
|
2
|
+
|
|
3
|
+
[](https://github.com/liking-initiative/likingInitiative-py/actions/workflows/ci.yml)
|
|
4
|
+
[](https://doi.org/10.5281/zenodo.22216442)
|
|
5
|
+
|
|
6
|
+
The Liking Rating Database in Python: subjective liking ratings from
|
|
7
|
+
published decision-making studies, as [polars](https://pola.rs) frames.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install git+https://github.com/liking-initiative/likingInitiative-py
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Requires Python 3.9 or newer. Data is downloaded from Zenodo on first use and
|
|
16
|
+
cached locally; no account or token is needed.
|
|
17
|
+
|
|
18
|
+
## Use
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
import likingInitiative
|
|
22
|
+
|
|
23
|
+
likingInitiative.list_datasets() # 59 datasets
|
|
24
|
+
likingInitiative.list_studies() # 38 studies
|
|
25
|
+
likingInitiative.list_items() # 2,217 stimuli
|
|
26
|
+
|
|
27
|
+
d = likingInitiative.get_dataset("leeholyoak2021")
|
|
28
|
+
d.data # polars DataFrame
|
|
29
|
+
d.scale # (1.0, 100.0)
|
|
30
|
+
d.timepoints # [1, 2, 3]
|
|
31
|
+
print(d.cite())
|
|
32
|
+
|
|
33
|
+
likingInitiative.get_dataset(["leeholyoak2021", "leehare2023exp2"]).data # stacked
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### One item across every study that used it
|
|
37
|
+
|
|
38
|
+
The cross-study view — the thing this database is built for:
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
k = likingInitiative.get_item("kitkat") # 1,626 ratings across 25 datasets
|
|
42
|
+
k.by_dataset() # mean / sd / median per study, 0-1 scale
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### The whole corpus
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
db = likingInitiative.load_database()
|
|
49
|
+
db["ratings"] # 759,399 rows
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Two things to get right
|
|
53
|
+
|
|
54
|
+
**Cross-study comparisons must use `normalized_rating`.** Studies use
|
|
55
|
+
different response scales (0–4, 1–100, 1–870, willingness-to-pay in dollars),
|
|
56
|
+
so raw `rating` values are not comparable. `normalized_rating` is
|
|
57
|
+
`(rating − scale_min) / (scale_max − scale_min)` and always lies in 0–1.
|
|
58
|
+
|
|
59
|
+
**Subject ids are unique only within a dataset.** Subject `"12"` in two
|
|
60
|
+
datasets is two different people — key on `(dataset_code, subject_id)`.
|
|
61
|
+
|
|
62
|
+
## Repeated rating phases
|
|
63
|
+
|
|
64
|
+
Six datasets repeat the whole rating phase (`chenhol1`, `chenhol2`,
|
|
65
|
+
`crosswebb`, `hamesmcc`, `leehare2023exp2`, `leeholyoak2021`), so
|
|
66
|
+
`(subject_id, item_id)` alone is not unique for them:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
d = likingInitiative.get_dataset("leeholyoak2021") # phases 1, 2, 3
|
|
70
|
+
d.data.group_by("timepoint").agg(pl.col("normalized_rating").mean())
|
|
71
|
+
|
|
72
|
+
likingInitiative.get_dataset("leeholyoak2021", timepoint=2) # one phase
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`get_item()` uses each dataset's first phase only, so a repeated-phase study
|
|
76
|
+
does not carry extra weight in a cross-study comparison.
|
|
77
|
+
|
|
78
|
+
## Versions and caching
|
|
79
|
+
|
|
80
|
+
Data comes from versioned release files, not a live service, so a pinned
|
|
81
|
+
version returns the same rows however long from now.
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
likingInitiative.release_info() # version, date, counts, migrations applied
|
|
85
|
+
likingInitiative.get_dataset("leeholyoak2021", version="1.6.2") # pin it
|
|
86
|
+
likingInitiative.cache_info(); likingInitiative.clear_cache()
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Set `LIKING_INITIATIVE_RELEASE_DIR` to a directory built by
|
|
90
|
+
`scripts/build_release.py` to work against an unreleased build.
|
|
91
|
+
|
|
92
|
+
## API
|
|
93
|
+
|
|
94
|
+
| Function | Returns |
|
|
95
|
+
|----------|---------|
|
|
96
|
+
| `list_studies()` / `list_datasets()` / `list_items()` | catalogue frames |
|
|
97
|
+
| `get_dataset(code, version, timepoint)` | `Dataset` — `.data`, `.metadata`, `.cite()` |
|
|
98
|
+
| `get_item(name, version)` | `Item` — `.data`, `.by_dataset()`, `.cite()` |
|
|
99
|
+
| `load_database(version)` | dict of frames |
|
|
100
|
+
| `cite(x)` / `bibtex(x)` | citation text |
|
|
101
|
+
| `release_info()` / `cache_info()` / `clear_cache()` | housekeeping |
|
|
102
|
+
|
|
103
|
+
## Citation
|
|
104
|
+
|
|
105
|
+
Please cite the database and the studies whose data you use. `cite()` with no
|
|
106
|
+
argument returns the database citation; `cite(d)` returns a study's.
|
|
107
|
+
|
|
108
|
+
> Fernandez, K., Goyal, S., & Krajbich, I. (2026). The Liking Initiative: a
|
|
109
|
+
> database of subjective evaluation ratings for decision-making research
|
|
110
|
+
> [Data set]. Zenodo. https://doi.org/10.5281/zenodo.22216442
|
|
111
|
+
|
|
112
|
+
That is the concept DOI, which always resolves to the newest version. To name
|
|
113
|
+
the exact bytes an analysis ran on, cite the version DOI that Zenodo lists for
|
|
114
|
+
the version `release_info()` reports.
|
|
115
|
+
|
|
116
|
+
## License
|
|
117
|
+
|
|
118
|
+
MIT. The underlying data remain subject to the terms of the original
|
|
119
|
+
publications.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "likingInitiative"
|
|
7
|
+
version = "0.2.1"
|
|
8
|
+
description = "The Liking Rating Database in Python"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Kianté Fernandez" }]
|
|
13
|
+
keywords = ["psychology", "decision-making", "open-data", "preference", "liking"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Science/Research",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Operating System :: OS Independent",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.9",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Topic :: Scientific/Engineering",
|
|
26
|
+
"Typing :: Typed",
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"polars>=0.20",
|
|
30
|
+
"requests>=2.28",
|
|
31
|
+
"platformdirs>=3.0",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
dev = ["pytest>=7", "ruff>=0.5", "build", "twine"]
|
|
36
|
+
|
|
37
|
+
[project.urls]
|
|
38
|
+
Homepage = "https://github.com/liking-initiative/likingInitiative-py"
|
|
39
|
+
Source = "https://github.com/liking-initiative/likingInitiative-py"
|
|
40
|
+
Issues = "https://github.com/liking-initiative/likingInitiative-py/issues"
|
|
41
|
+
Changelog = "https://github.com/liking-initiative/likingInitiative-py/blob/main/CHANGELOG.md"
|
|
42
|
+
Data = "https://doi.org/10.5281/zenodo.22216442"
|
|
43
|
+
|
|
44
|
+
[tool.setuptools.packages.find]
|
|
45
|
+
where = ["src"]
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.package-data]
|
|
48
|
+
likingInitiative = ["py.typed"]
|
|
49
|
+
|
|
50
|
+
[tool.ruff]
|
|
51
|
+
line-length = 100
|
|
52
|
+
target-version = "py39"
|
|
53
|
+
|
|
54
|
+
[tool.ruff.lint]
|
|
55
|
+
# Pinned explicitly so a newer ruff on CI cannot widen the rule set. The
|
|
56
|
+
# package is deliberately camelCase (it matches the R package), so
|
|
57
|
+
# pep8-naming's module-name rule is not selected.
|
|
58
|
+
select = ["E", "F", "W", "I"]
|
|
59
|
+
|
|
60
|
+
[tool.ruff.lint.isort]
|
|
61
|
+
known-first-party = ["likingInitiative"]
|
|
62
|
+
|
|
63
|
+
[tool.pytest.ini_options]
|
|
64
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""
|
|
2
|
+
likingInitiative — the Liking Rating Database in Python.
|
|
3
|
+
|
|
4
|
+
Subjective liking ratings from published decision-making studies, as polars
|
|
5
|
+
frames.
|
|
6
|
+
|
|
7
|
+
import likingInitiative
|
|
8
|
+
|
|
9
|
+
likingInitiative.list_datasets() # the catalogue
|
|
10
|
+
d = likingInitiative.get_dataset("leeholyoak2021") # one study's ratings
|
|
11
|
+
d.data # polars DataFrame
|
|
12
|
+
d.cite()
|
|
13
|
+
|
|
14
|
+
likingInitiative.get_item("kitkat") # one item, every study
|
|
15
|
+
likingInitiative.load_database() # the whole corpus
|
|
16
|
+
|
|
17
|
+
Data comes from versioned release files, not a live service, so a pinned
|
|
18
|
+
version returns the same rows however long from now. Assets are cached
|
|
19
|
+
locally after first download — see ``cache_info()``.
|
|
20
|
+
|
|
21
|
+
Two things to get right:
|
|
22
|
+
|
|
23
|
+
* **Cross-study comparisons must use ``normalized_rating``.** Response scales
|
|
24
|
+
differ between studies (0-4, 1-100, 1-870, willingness-to-pay in dollars),
|
|
25
|
+
so raw ``rating`` values are not comparable. ``normalized_rating`` is
|
|
26
|
+
``(rating - scale_min) / (scale_max - scale_min)`` and always lies in 0-1.
|
|
27
|
+
* **Subject ids are unique only within a dataset.** Subject "12" in two
|
|
28
|
+
datasets is two different people; key on ``(dataset_code, subject_id)``.
|
|
29
|
+
"""
|
|
30
|
+
from .catalog import list_datasets, list_items, list_studies, release_info
|
|
31
|
+
from .citation import bibtex, cite
|
|
32
|
+
from .database import load_database
|
|
33
|
+
from .dataset import Dataset, get_dataset
|
|
34
|
+
from .item import Item, get_item
|
|
35
|
+
from .release import (
|
|
36
|
+
LikingInitiativeError,
|
|
37
|
+
cache_info,
|
|
38
|
+
clear_cache,
|
|
39
|
+
resolve_version,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
__all__ = [
|
|
43
|
+
"list_studies",
|
|
44
|
+
"list_datasets",
|
|
45
|
+
"list_items",
|
|
46
|
+
"get_dataset",
|
|
47
|
+
"get_item",
|
|
48
|
+
"load_database",
|
|
49
|
+
"cite",
|
|
50
|
+
"bibtex",
|
|
51
|
+
"release_info",
|
|
52
|
+
"resolve_version",
|
|
53
|
+
"cache_info",
|
|
54
|
+
"clear_cache",
|
|
55
|
+
"Dataset",
|
|
56
|
+
"Item",
|
|
57
|
+
"LikingInitiativeError",
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
__version__ = "0.2.1"
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""The release catalogue: studies, datasets, and items."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Dict
|
|
5
|
+
|
|
6
|
+
import polars as pl
|
|
7
|
+
|
|
8
|
+
from .release import LikingInitiativeError, asset_path, load_catalog
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def release_info(version: str = "latest") -> Dict[str, Any]:
|
|
12
|
+
"""Version, date, and headline counts for the release in use."""
|
|
13
|
+
return load_catalog(version)["release"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def list_studies(version: str = "latest") -> pl.DataFrame:
|
|
17
|
+
"""Every publication in the database."""
|
|
18
|
+
return pl.DataFrame(load_catalog(version)["studies"])
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def list_datasets(version: str = "latest") -> pl.DataFrame:
|
|
22
|
+
"""Every dataset, with its study, response scale, and size.
|
|
23
|
+
|
|
24
|
+
``timepoints`` lists the rating phases a dataset holds; all but two have
|
|
25
|
+
a single phase.
|
|
26
|
+
"""
|
|
27
|
+
rows = load_catalog(version)["datasets"]
|
|
28
|
+
frame = pl.DataFrame(rows, infer_schema_length=None)
|
|
29
|
+
return frame.with_columns(
|
|
30
|
+
pl.col("timepoints").list.len().alias("n_timepoints")
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def list_items(version: str = "latest") -> pl.DataFrame:
|
|
35
|
+
"""Every stimulus, with the number of datasets it appears in."""
|
|
36
|
+
return pl.read_csv(
|
|
37
|
+
asset_path("items.tsv", version),
|
|
38
|
+
separator="\t",
|
|
39
|
+
schema_overrides={"item_id": pl.String, "name": pl.String},
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def dataset_entry(code: str, version: str = "latest") -> Dict[str, Any]:
|
|
44
|
+
"""Look up one dataset's catalogue entry by code, id, or unique prefix."""
|
|
45
|
+
datasets = load_catalog(version)["datasets"]
|
|
46
|
+
lowered = code.lower()
|
|
47
|
+
|
|
48
|
+
for d in datasets:
|
|
49
|
+
if d["dataset_code"].lower() == lowered or d["dataset_id"] == code:
|
|
50
|
+
return d
|
|
51
|
+
|
|
52
|
+
prefix = [d for d in datasets if d["dataset_code"].lower().startswith(lowered)]
|
|
53
|
+
if len(prefix) == 1:
|
|
54
|
+
return prefix[0]
|
|
55
|
+
if len(prefix) > 1:
|
|
56
|
+
names = ", ".join(sorted(d["dataset_code"] for d in prefix))
|
|
57
|
+
raise LikingInitiativeError(f"'{code}' is ambiguous; matches: {names}")
|
|
58
|
+
|
|
59
|
+
raise LikingInitiativeError(
|
|
60
|
+
f"no dataset named '{code}'. Use likingInitiative.list_datasets() to see the catalogue."
|
|
61
|
+
)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Citations for the database and for the studies it draws on."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Optional
|
|
5
|
+
|
|
6
|
+
# The concept DOI, which Zenodo resolves to the newest version. Cite this to
|
|
7
|
+
# mean "the database"; cite the version DOI that release_info() reports when an
|
|
8
|
+
# analysis needs to name the exact bytes it ran on.
|
|
9
|
+
DATABASE_DOI = "10.5281/zenodo.22216442"
|
|
10
|
+
|
|
11
|
+
DATABASE_CITATION = (
|
|
12
|
+
"Fernandez, K., Goyal, S., & Krajbich, I. (2026). The Liking Initiative: a "
|
|
13
|
+
"database of subjective evaluation ratings for decision-making research "
|
|
14
|
+
"[Data set]. Zenodo. https://doi.org/" + DATABASE_DOI
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _entry(x: Any) -> Optional[dict]:
|
|
19
|
+
"""Accept a Dataset/Item object or a raw catalogue dict."""
|
|
20
|
+
if x is None:
|
|
21
|
+
return None
|
|
22
|
+
if isinstance(x, dict):
|
|
23
|
+
return x
|
|
24
|
+
return getattr(x, "metadata", None)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def cite(x: Any = None) -> str:
|
|
28
|
+
"""Citation for a dataset's source publication.
|
|
29
|
+
|
|
30
|
+
Returns only that study's citation. Appending the database's every time
|
|
31
|
+
would be noise in a loop over datasets -- call ``cite()`` with no argument
|
|
32
|
+
for the database's own citation, and please include it alongside whichever
|
|
33
|
+
studies you use.
|
|
34
|
+
"""
|
|
35
|
+
entry = _entry(x)
|
|
36
|
+
if entry is None:
|
|
37
|
+
return DATABASE_CITATION
|
|
38
|
+
|
|
39
|
+
citation = entry.get("citation") or entry.get("study_name") or ""
|
|
40
|
+
doi = entry.get("paper_doi")
|
|
41
|
+
if doi:
|
|
42
|
+
citation = f"{citation} https://doi.org/{doi}"
|
|
43
|
+
return citation
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def bibtex(x: Any) -> str:
|
|
47
|
+
"""A BibTeX entry for a dataset's source publication."""
|
|
48
|
+
entry = _entry(x)
|
|
49
|
+
if entry is None:
|
|
50
|
+
raise ValueError("bibtex() needs a dataset or item")
|
|
51
|
+
|
|
52
|
+
authors = " and ".join(
|
|
53
|
+
a.strip() for a in (entry.get("authors") or "").split(";") if a.strip()
|
|
54
|
+
)
|
|
55
|
+
year = entry.get("year") or ""
|
|
56
|
+
first = (entry.get("first_author") or "study").lower().replace(" ", "")
|
|
57
|
+
fields = [
|
|
58
|
+
f" author = {{{authors}}}",
|
|
59
|
+
f" title = {{{entry.get('study_name', '')}}}",
|
|
60
|
+
f" year = {{{year}}}",
|
|
61
|
+
]
|
|
62
|
+
if entry.get("journal"):
|
|
63
|
+
fields.append(f" journal = {{{entry['journal']}}}")
|
|
64
|
+
if entry.get("paper_doi"):
|
|
65
|
+
fields.append(f" doi = {{{entry['paper_doi']}}}")
|
|
66
|
+
return "@article{" + f"{first}{year}" + ",\n" + ",\n".join(fields) + "\n}"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""load_database() — the whole corpus in one call."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Dict
|
|
5
|
+
|
|
6
|
+
import polars as pl
|
|
7
|
+
|
|
8
|
+
from .catalog import list_items, list_studies
|
|
9
|
+
from .release import asset_path, load_catalog
|
|
10
|
+
|
|
11
|
+
_cache: Dict[str, Dict[str, pl.DataFrame]] = {}
|
|
12
|
+
|
|
13
|
+
_SCHEMA = {
|
|
14
|
+
"subject_id": pl.String,
|
|
15
|
+
"item_id": pl.String,
|
|
16
|
+
"item_name": pl.String,
|
|
17
|
+
"dataset_code": pl.String,
|
|
18
|
+
"study_id": pl.String,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def load_database(version: str = "latest") -> Dict[str, pl.DataFrame]:
|
|
23
|
+
"""Every rating, plus the study, dataset and item tables.
|
|
24
|
+
|
|
25
|
+
Returns ``{"ratings", "studies", "datasets", "items"}``. Held in memory
|
|
26
|
+
after the first call, so repeated use is free.
|
|
27
|
+
"""
|
|
28
|
+
resolved = load_catalog(version)["release"]["version"]
|
|
29
|
+
if resolved in _cache:
|
|
30
|
+
return _cache[resolved]
|
|
31
|
+
|
|
32
|
+
ratings = pl.read_csv(
|
|
33
|
+
asset_path("ratings.tsv.gz", version),
|
|
34
|
+
separator="\t",
|
|
35
|
+
schema_overrides=_SCHEMA,
|
|
36
|
+
)
|
|
37
|
+
datasets = pl.DataFrame(load_catalog(version)["datasets"], infer_schema_length=None)
|
|
38
|
+
|
|
39
|
+
out = {
|
|
40
|
+
"ratings": ratings,
|
|
41
|
+
"studies": list_studies(version),
|
|
42
|
+
"datasets": datasets,
|
|
43
|
+
"items": list_items(version),
|
|
44
|
+
}
|
|
45
|
+
_cache[resolved] = out
|
|
46
|
+
return out
|