k-anonymity package
Evaluate if a tabular dataset respect k-anonymity handling missing values in the dataset. K-anonymity stands for having at least k similar rows for each row in the dataset, including itself. A missing value has value of any other category, having missing values increase the deidentification. This package includes a function to add the minimum number of missing values to reach k-anonymity of the dataset.
Installation
uv add kanonymity
Important information
The current version of the pipeline does not directly handle longitudinal data. You should take care of deciding how to consider duplicates subjects. One example here, where it is decided to keep most common answer, but you could also decide to replace answers that changes accross one subject by missing value, or consider the different rows as different individuals:
# df is the original complete dataframe
# replace "subject_id" by the name of the ID column
# quasi_identifiers is a list of quasi-identifiers column names
# index_table helps to reduplicate rows in the end in case some modification of the dataframe is done
table = df.groupby(["subject_id"]+quasi_identifiers, dropna=False).size().to_frame('size').reset_index()
index_table = df.groupby(['subject_id'], dropna=False).apply(lambda x: x.index.tolist()).to_frame('original_index').reset_index()
index_table = index_table.sort_values(['subject_id'], ascending=[True])
df = table.sort_values(["subject_id", "size"], ascending=[True, False]).drop_duplicates(subset=["subject_id"], keep="first")
df = df.drop('size', axis=1)
Here is how to reduplicate the subjects that had several rows in the original dataset:
# df is the new version of the deduplicated dataset that had potential modifications to increase deidentification
# original_df is the dataframe before these potential modifications
for r in range(len(df)):
if not original_df.iloc[r].equals(df.iloc[r]):
indexes = index_table['original_index'].iloc[r]
for i in indexes:
for feature in quasi_identifiers:
if feature.split('_')[0] not in numerical_QI:
flat_df.loc[i, feature] = df[feature].iloc[r]
else:
if original_df[feature].iloc[r] != df[feature].iloc[r]:
flat_df[feature.split('_')[0]].iloc[i] = np.nan
In addition, the quasi-identifiers have to be categorical columns. You can use relevant bins to convert numerical to categorical.
Functions details
check_k_anonymity(df, quasi_identifier_cols, k)returns the number of rows that don't have enough similar rows, and are at risk of reidentification. The columns to considere are given in a listquasi_identifers_colsand the number of similar rows to have, including the row itself isk. It also returns a summary df of every combination of each categories combinations that exists in the dataset. Missing values are counting as if they could be any existing category. If a featureAcan have0or1as categories, a row with missingAwould count as two rows, one with0and one with1.safe_combinations(df, quasi_identifiers, k, min_combi_size=2, max_combi_size=None)checks which combinations of features validates k-anonymity. In case you have a large number of quasi-identifiers, you can set boundaries to the number of features to consider in your combinations. The result is given as a list of lists.min_missingness_max_deid(df, QI, k, maximum_missingness=25, excluded_features=None, step=0.001, n_random_trials=25)adds the same percentage of missing values in every quasi-identifier feature, with a maximum ofmaximum_missingnessto reach no risk of reidentification. Binary search is implemented to find the lowest percentage that allows no risk of reidentification, with several random trials as the position of the missing values impacts the k-anonymity. The step defines the precision of the percentage and the function allows to exclude some columns from the missingness addition. If themaximum_missingnessthreshold doesn't allow to earase the risk of reidentification, it returns the dataframe with the minimum number of rows at risk of reidentification. The function returns the most deidentified dataframe with the minimum addition of missingness possible, the percentage of missingness added to each column and the number of rows that are at risk of reidentification.
Metadata
Release files for kanonymity 0.1.0
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 | Actions |
|---|---|---|---|---|
| kanonymity-0.1.0.tar.gz | 7.6 kB | Without provenance | Details for kanonymity-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| kanonymity-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for kanonymity-0.1.0-py3-none-any.whl |
Total release size: 13.7 kB
Release files / kanonymity-0.1.0.tar.gz
| Download URL | kanonymity-0.1.0.tar.gz |
|---|---|
| Size | 7.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d62ce1c9508093a4e0f1ca7df88eca341efe47804625470bd6d95675dca6690e
|
|
BLAKE2b-256 checksum How to use checksums |
4e231faf9d312e8b9e1ac5245c5bc8b5f616bbfcbc410f65e5cb12e057b5e068
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / kanonymity-0.1.0-py3-none-any.whl
| Download URL | kanonymity-0.1.0-py3-none-any.whl |
|---|---|
| Size | 6.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
eb2b179958a466065dce6b8876846c30b2411e09a9e5f5623d521bbeb51510f2
|
|
BLAKE2b-256 checksum How to use checksums |
9668d3f10d7b8d55bbdd5353aec983c3947763addb42dbf8b7354c39d0ac1407
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Security for kanonymity 0.1.0
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.
To learn more about protecting yourself from malicious actors, visit our package security documentation.