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 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