from __future__ import division
from collections import Counter
import numpy as np
import pandas as pd

class DataFrameSummary(object):

    # define global variables
    TYPE_BOOL = 'bool'
    TYPE_NUMERIC = 'numeric'
    TYPE_DATE = 'date'
    TYPE_CATEGORICAL = 'categorical'
    TYPE_CONSTANT = 'constant'
    TYPE_UNIQUE = 'unique'


    def __init__(self, df):
        self.df = df
        self.columns = df.columns
        self.shape = df.shape
        self.row_count = df.shape[0]
        self.count = df.count()


    def get_column_types(self):
        '''get column type of each column in dataframe'''
        types = [[col, self.df[col].dtype, 'dtypes'] for col in self.columns]
        col_types_df = pd.DataFrame(types,
                                    columns=['column_name',
                                             'value',
                                             'variable'])
        return col_types_df


    def get_missing_count(self):
        '''get raw count of missing values in each column'''
        missing_cnt = [[x,
                        self.row_count - self.count[i],
                        'missing_count'] for i, x in enumerate(self.columns)]
        missing_cnt_df = pd.DataFrame(missing_cnt,
                                      columns=['column_name',
                                               'value',
                                               'variable'])
        return missing_cnt_df


    def get_missing_percentage(self):
        '''get proportion of missing values in each column of dataframe'''
        missing_percent = [[x,
                           (self.count[i] / self.row_count)*100,
                           'missing_%'] for i, x in enumerate(self.columns)]
        missing_percent_df = pd.DataFrame(missing_percent,
                                          columns=['column_name',
                                                   'value',
                                                   'variable'])
        return missing_percent_df


    def get_summary(self):
        '''collect all column summaries and return as dataframe'''
        col_types_df = self.get_column_types()
        missing_cnt_df = self.get_missing_count()
        missing_percent_df = self.get_missing_percentage()
        df_summary = pd.concat([col_types_df,
                                missing_cnt_df,
                                missing_percent_df])
        df_summary = df_summary.pivot(index='variable',
                                      columns='column_name',
                                      values='value')
        df_summary.index.name = None
        return df_summary
@@ -97,16 +97,17 @@
  as pd%0A%0A
+%0A
 class Da
@@ -529,411 +529,1396 @@
 def 
-get_column_types(self):%0A        '''get column type of each column in dataframe'''%0A        types = %5B%5Bcol, self.df%5Bcol%5D.dtype, 'dtypes'%5D for col in self.columns%5D%0A        col_types_df = pd.DataFrame(types,%0A                                    columns=%5B'column_name',%0A                                             'value',%0A                                             'variable'%5D)%0A        return col_types_df%0A
+in_ipynb():%0A        '''%0A        check if code is running in ipython notebook or jupyter%0A        taken from SO thread:%0A        http://stackoverflow.com/questions/15411967/how-can-i-check-if-code-is-executed-in-the-ipython-notebook%0A        '''%0A        try:%0A            cfg = get_ipython().config %0A            if cfg%5B'IPKernelApp'%5D%5B'parent_appname'%5D == 'ipython-notebook':%0A                return True%0A            else:%0A                return False%0A        except NameError:%0A            return False%0A%0A%0A    def get_column_types(self):%0A        '''get column type of each column in dataframe'''%0A        types = %5B%5Bcol, self.df%5Bcol%5D.dtype, 'dtypes'%5D for col in self.columns%5D%0A        col_types_df = pd.DataFrame(types,%0A                                    columns=%5B'column_name',%0A                                             'value',%0A                                             'variable'%5D)%0A        return col_types_df%0A%0A%0A    def get_unique_count(self):%0A        '''get number of unique values in each column'''%0A        unique_cnt = %5B%5Bcol,%0A                       self.df%5Bcol%5D.nunique(),%0A                       'unique_count'%5D for col in self.columns%5D%0A        unique_cnt_df = pd.DataFrame(unique_cnt,%0A                                    columns=%5B'column_name',%0A                                             'value',%0A                                             'variable'%5D)%0A        return unique_cnt_df
 %0A%0A  
@@ -3143,16 +3143,64 @@
 types()%0A
+        unique_cnt_df = self.get_unique_count()%0A
         
@@ -3342,24 +3342,71 @@
 l_types_df,%0A
+                                unique_cnt_df,%0A
             
@@ -3719,16 +3719,380 @@
 eturn df_summary
+%0A%0A%0A    def get_distributions(self):%0A        '''generate distribution plots and summary statistics'''%0A        import matplotlib.pyplot as plt%0A        plt.style.use('fivethirtyeight')%0A        if in_ipynb:%0A%0A        else:%0A%0A        numeric_df = self.df._get_numeric_data()%0A        f = open('/home/jack/report.html','w')%0A        f.write(html_string)%0A        f.close()%0A%0A%0A

add in_ipynb function