import numpy as np
import scipy.stats
import pandas as pd

####################################### Working 2D Data using np.array ##########################
a = np.array([[1, 6, 1],
              [2, 3, 1],
              [4, 9, 2],
              [8, 27, 4],
              [16, 1, 1]])

print(a)

############## Statistics for entire dataset ##########################
print("\nStatistics over entire dataset")
print("Arithmetic Mean using np.mean(): ",np.mean(a, axis=None)) 
print("Arithmetic Mean using a.mean(): ",a.mean(axis=None))
print("Geometric Mean using scipy.stats.gmean(): ",scipy.stats.gmean(a,axis=None))
print("Median: ",np.median(a,axis=None))
print("Variance: ",a.var(ddof=1, axis=None))
print("Statistics using scipy.stats.describe(): ",scipy.stats.describe(a, axis=None, ddof=1, bias=False))
print()
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

################ Statistics for each column ###############
print("\n Statistics for each column")
print("Arithmetic Mean for 1st column using np.mean(): ",np.mean(a, axis=0)) #mean over each column
print("Arithmetic Mean for 1st column using a.mean(): ",a.mean(axis=0))
print("Geometric Mean using scipy.stats.gmean(): ",scipy.stats.gmean(a,axis=0))
print("Median: ",np.median(a, axis=0))
print("Variance: ",a.var(ddof=1, axis=0))
print("Statistics using scipy.stats.describe(): ",scipy.stats.describe(a,axis=0, ddof=1, bias=False))
print()
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

######### Statistics for each row ######################
print("\n Statistics for each row")
print("Arithmetic Mean for 1st column using np.mean(): ",np.mean(a, axis=1)) #mean over each row
print("Arithmetic Mean for 1st column using a.mean(): ",a.mean(axis=1))
print("Geometric Mean using scipy.stats.gmean(): ",scipy.stats.gmean(a,axis=1))
print("Median: ",np.median(a, axis=1))
print("Variance: ",a.var(ddof=1, axis=1))
print("Statistics using scipy.stats.describe(): ",scipy.stats.describe(a,axis=1, ddof=1, bias=False))
print()
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

############ Specific Values from the function scipy.stats.describe() #####################
result = scipy.stats.describe(a, axis=1, ddof=1, bias=False)
print("\n Arithmetic Mean from the function scipy.stats.describe(): ",result.mean)
print()
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

############################# Working 2D Data using dataframes ############################
print("\n Working 2D Data using dataframes")
row_names = ['first', 'second', 'third', 'fourth', 'fifth']
col_names = ['A', 'B', 'C']
df = pd.DataFrame(a, index=row_names, columns=col_names)
print("\n DF",df)
print("\n Statistics for each row for the dataframe")
print("\n Arithmetic Mean for each row:", df.mean(axis=1))
print("\n Variance for each row:",df.var(axis=1))
print()
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

################# Isolation of each column of the DataFrame and statistics upon this ################
print("\nColumn 'A' of the DataFrame:")
print(df['A'])
print("mean over column 'A': ",df['A'].mean())
print("variance over column 'A': ",df['A'].var())
print()
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

################## Get all data from a DataFrame with .values or .to_numpy(): #####################
print("\n DataFrame as numpy array")
print("Using df.values:\n",df.values)
print("Using df.values:\n",df.to_numpy())
print()
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

################### Many statistics over dataframe ###########################################
print("\n df.describe():\n",df.describe())
print("Arithmetic Mean using df.describe(): ",df.describe().at['mean', 'A'])
print("percentiles using df.describe(): ",df.describe().at['50%', 'B'])