import pandas as pd from sklearn.model_selection import train_test_split import config from utils.general import * import utils.Google.Docs.read_sheet as gdoc def get_keywords(df, which='Release'): ''' Searches gDoc dataframe for keywords for ArtistName or ReleaseName. Returns line-delimted string of list of keywords. Called only from get_filters() ''' keys = df[ df[config.gdoc_col].isin(['Both', which]) ]['Keywords'].tolist() if keys: return '|'.join(keys) else: return def get_filters(sheet): ''' Breaks keywords and catagory into a dictionary containing which field to search for which keywords. ''' df_filter = gdoc.sheet_2_df(id=config.sheet_id, sheet=sheet, range=config.sheet_range) filter_dict = dict() df_filter[config.gdoc_col] = df_filter[config.gdoc_col].str.strip() df_filter['Keywords'] = df_filter['Keywords'].str.lstrip().str.rstrip() # search for Release and Both filter_dict['RELEASENAME'] = get_keywords(df_filter, which='Release') # search for Artist and Both filter_dict['ARTISTNAME'] = get_keywords(df_filter, which='Artist') for key in ['RELEASENAME', 'ARTISTNAME']: if not filter_dict[key]: filter_dict.pop(key, None) return filter_dict def find_keywords(df, keywords): ''' Takes the dictionary from get_filters() and the entire dataset. Searches the releasename and the artistname for keywords. True is returned if either row gets a hit. ''' release_keys = keywords.get('RELEASENAME') artist_keys = keywords.get('ARTISTNAME') if release_keys and artist_keys: hits = df['RELEASENAME'].str.contains(release_keys, case=False) \ | df['ARTISTNAME'].str.contains(artist_keys, case=False) elif release_keys and not artist_keys: hits = df['RELEASENAME'].str.contains(release_keys, case=False) elif artist_keys and not release_keys: hits = df['ARTISTNAME'].str.contains(artist_keys, case=False) return hits def get_features_target(columns): ''' Splits between the target and the features. ''' target = config.target features = [c for c in columns if c != target] return features, target def get_new(): df = pull_training_data(how='new') return df def get_catalog(): df = pull_training_data(how='cat') return df def get_train_test_split(): df = pull_training_data(how='train') print('6. splitting data into train and test set.') features, target = get_features_target(df.columns) X, y = df[features], df[target] X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=42) return X_train, X_test, y_train, y_test def pull_training_data(how='train'): ''' Almost all of the steps needed to reshape data we're going to feed into our model how='train', will just return reviewed tracks (this is good for model training) how='full_cat' (or anything else), will return all reviewed tracks and the entirety of the unreviewed catalog. Options: Pull new data -- 'new' Returns X, y Pull catalog (not reviewed) -- 'cat': Returns X Pull all-reviewed -- 'train': Returns X_train, X_test, y_train, y_test Need metadata for all these options... ''' print("1. initial pull from Snowflake") if how == 'train': df = sf.q(query.query_train, dtype='O', resp='df') elif how == 'cat': df = sf.q(query.query_full_cat, dtype='O', resp='df') else: df = sf.q(query.query_new_reviews, dtype='O', resp='df') print("2. preprocessing {} rows".format(len(df))) # remove null values non_nulls = [c for c in df.columns if c not in config.null_cols] df = df[~pd.isnull(df[non_nulls]).any(axis=1)] # convert strings floats, because we need to read df as object because of UPC. df = df.astype(config.dtypes) # need to configure google docs creds!! print("3. getting keywords from: https://docs.google.com/spreadsheets/d/{}".format(config.sheet_id)) args = dict() sheets = gdoc.get_sheet_ids(config.sheet_id) for sheet in sheets: if sheet not in config.tabs_to_exclude: args[sheet] = get_filters(sheet) for col, keywords in args.items(): new_col_name = "IS_{}".format(col.upper().replace(' ','_')) df[new_col_name] = find_keywords(df, keywords=keywords) df['IS_COMPILATION'] = df[['IS_COMPILATION', 'IS_COMPILATION_X']].max(axis=1) df.drop('IS_COMPILATION_X', axis=1, inplace=True) print("4. sparsifying matrix") df = pd.get_dummies(df, columns=['GENREID']) # remove the genreID placeholders! see ln#156 in config.py df = df[df['NOTE'] != '999'] print("5. cleaning up target values") df['APPROVED'] = df['APPROVED'].replace(config.target_dictionary) return df def reverse_dummy(df_dummies): ''' Used to de-sparsify a matrix. Taken for S.O. http://stackoverflow.com/a/34523806/5094480 ''' from collections import defaultdict pos = defaultdict(list) vals = defaultdict(list) for i, c in enumerate(df_dummies.columns): if "_" in c: k, v = c.split("_", 1) pos[k].append(i) vals[k].append(v) else: pos["_"].append(i) df = pd.DataFrame({k: pd.Categorical.from_codes( np.argmax(df_dummies.iloc[:, pos[k]].values, axis=1), vals[k]) for k in vals}) df[df_dummies.columns[pos["_"]]] = df_dummies.iloc[:, pos["_"]] return df