Source code for acore.utils

from collections.abc import Iterable

import numpy as np
import pandas as pd


[docs] def convertToEdgeList(data, cols): """ This function converts a pandas dataframe to an edge list where index becomes the source nodes and columns the target nodes. :param data: pandas dataframe. :param list cols: names for dataframe columns. :return: Pandas dataframe with columns cols. """ data.index.name = None edge_list = data.stack().reset_index() edge_list.columns = cols return edge_list
# TODO move to dsp_pandas
[docs] def check_is_paired(df, subject, group): """ Check if samples are paired. :param df: pandas dataframe with samples as rows and protein identifiers as columns (with additional columns 'group', 'sample' and 'subject'). :param str subject: column with subject identifiers :param str group: column with group identifiers :return: True if paired samples. :rtype: bool """ is_pair = False if subject is not None: count_subject_groups = df.groupby(subject)[group].count() is_pair = (count_subject_groups > 1).all() return is_pair
[docs] def transform_into_wide_format(data, index, columns, values, extra=[]): """ This function converts a Pandas DataFrame from long to wide format using pandas pivot_table() function. :param data: long-format Pandas DataFrame :param list index: columns that will be converted into the index :param str columns: column name whose unique values will become the new column names :param str values: column to aggregate :param list extra: additional columns to be kept as columns :return: Wide-format pandas DataFrame Example:: result = transform_into_wide_format(df, index='index', columns='x', values='y', extra='group') """ df = pd.DataFrame() extra_cols = None if data is not None: df = data.copy() if not df.empty: if index is None: df = df.reset_index() index = "index" cols = [] append_to_list(cols, columns) append_to_list(cols, values) append_to_list(cols, index) if len(extra) > 0: append_to_list(extra, index) extra_cols = df[extra].set_index(index) df = df[cols] df = df.drop_duplicates() if isinstance(index, list): df = df.pivot_table( index=index, columns=columns, values=values, aggfunc="first" ) else: df = df.pivot(index=index, columns=columns, values=values) if extra_cols is not None: df = df.join(extra_cols) df = df.drop_duplicates() df = df.reset_index() return df
[docs] def transform_into_long_format(data, drop_columns, group, columns=["name", "y"]): """ Converts a Pandas DataDrame from wide to long format using pd.melt() function. :param data: wide-format Pandas DataFrame :param list drop_columns: columns to be deleted :param group: column(s) to use as identifier variables :type group: str or list :param list columns: names to use for the 1)variable column, and for the 2)value column :return: Long-format Pandas DataFrame. Example:: result = transform_into_long_format(df, drop_columns=['sample', 'subject'], group='group', columns=['name','y']) """ long_data = pd.DataFrame() if data is not None: data = data.drop(drop_columns, axis=1) long_data = pd.melt( data, id_vars=group, var_name=columns[0], value_name=columns[1] ) long_data = long_data.set_index(group) long_data.columns = columns return long_data
[docs] def remove_group(data): """ Removes column with label 'group'. :param data: pandas dataframe with one column labelled 'group' :return: Pandas dataframe Example:: result = remove_group(data) """ data.drop(["group"], axis=1) return data
[docs] def calculate_fold_change(df, condition1, condition2): """ Calculates fold-changes between two groups for all proteins in a dataframe. :param df: pandas dataframe with samples as rows and protein identifiers as columns. :param str condition1: identifier of first group. :param str condition2: identifier of second group. :return: Numpy array. Example:: result = calculate_fold_change(data, 'group1', 'group2') """ group1 = df[condition1] group2 = df[condition2] if isinstance(group1, np.float64): group1 = np.array(group1) else: group1 = group1.values if isinstance(group2, np.float64): group2 = np.array(group2) else: group2 = group2.values if np.isnan(group1).all() or np.isnan(group2).all(): fold_change = np.nan else: fold_change = np.nanmedian(group1) - np.nanmedian(group2) return fold_change
[docs] def pooled_standard_deviation(sample1, sample2, ddof): """ Calculates the pooled standard deviation. For more information visit https://www.hackdeploy.com/learn-what-is-statistical-power-with-python/. :param array sample1: numpy array with values for first group :param array sample2: numpy array with values for second group :param int ddof: degrees of freedom """ # calculate the sample size n1, n2 = len(sample1), len(sample2) # calculate the variances var1, var2 = np.var(sample1, ddof=1), np.var(sample2, ddof=ddof) # calculate the pooled standard deviation numerator = ((n1 - 1) * var1) + ((n2 - 1) * var2) denominator = n1 + n2 - 2 return np.sqrt(numerator / denominator)
[docs] def cohens_d(sample1, sample2, ddof): """ Calculates Cohen's d effect size based on the distance between two means, measured in standard deviations. For more information visit https://www.hackdeploy.com/learn-what-is-statistical-power-with-python/. :param array sample1: numpy array with values for first group :param array sample2: numpy array with values for second group :param int ddof: degrees of freedom """ u1, u2 = np.mean(sample1), np.mean(sample2) s_pooled = pooled_standard_deviation(sample1, sample2, ddof) return (u1 - u2) / s_pooled
[docs] def hedges_g(df, condition1, condition2, ddof=0): """ Calculates Hedges’ g effect size (more accurate for sample sizes below 20 than Cohen's d). For more information visit https://docs.scipy.org/doc/numpy/reference/generated/numpy.nanstd.html. :param df: pandas dataframe with samples as rows and protein identifiers as columns. :param str condition1: identifier of first group. :param str condition2: identifier of second group. :param int ddof: means Delta Degrees of Freedom. :return: Numpy array. Example:: result = hedges_g(data, 'group1', 'group2', ddof=0) """ group1 = df[condition1] group2 = df[condition2] if isinstance(group1, np.float64): group1 = np.array(group1) else: group1 = group1.values if isinstance(group2, np.float64): group2 = np.array(group2) else: group2 = group2.values ng1 = group1.size ng2 = group2.size # dof = ng1 + ng2 - 2 if np.isnan(group1).all() or np.isnan(group2).all(): g = np.nan else: meang1 = np.nanmean(group1) meang2 = np.nanmean(group2) sdpooled = np.nanstd(np.concatenate([group1, group2]), ddof=ddof) # Correct bias small sample size if ng1 + ng2 < 50: g = ( ((meang1 - meang2) / sdpooled) * ((ng1 + ng2 - 3) / (ng1 + ng2 - 2.25)) * np.sqrt((ng1 + ng2 - 2) / (ng1 + ng2)) ) else: g = (meang1 - meang2) / sdpooled return g
[docs] def unit_vector(vector): """ Returns the unit vector of the vector. :param tuple vector: vector :return tuple unit_vector: unit vector """ return vector / np.linalg.norm(vector)
[docs] def flatten(t, my_list=[]): """ Code from: https://gist.github.com/shaxbee/0ada767debf9eefbdb6e Acknowledgements: Zbigniew Mandziejewicz (shaxbee) Generator flattening the structure >>> list(flatten([2, [2, (4, 5, [7], [2, [6, 2, 6, [6], 4]], 6)]])) [2, 2, 4, 5, 7, 2, 6, 2, 6, 6, 4, 6] """ for x in t: if not isinstance(x, Iterable) or isinstance(x, str): my_list.append(x) else: flatten(x, my_list) return my_list
[docs] def angle_between(v1, v2): """ Returns the angle in radians between vectors 'v1' and 'v2' :param tuple v1: vector 1 :param tuple v2: vector 2 :return float angle: angle between two vectors in radians Example:: angle = angle_between((1, 0, 0), (0, 1, 0)) """ v1_u = unit_vector(v1) v2_u = unit_vector(v2) return np.arccos(np.clip(np.dot(v1_u, v2_u), -1.0, 1.0))
[docs] def append_to_list(mylist, myappend): if isinstance(myappend, list): mylist.extend(myappend) else: mylist.append(myappend)
[docs] def generator_to_dict(genvar): dictvar = {} for i, gen in enumerate(genvar): dictvar.update({n: i for n in gen}) return dictvar