{"cells":[{"metadata":{},"cell_type":"markdown","source":"This notebook uses, a priori knowledge on the question and user to guess the outcome.\n\nThe idea is to gather user stats under dictionary variables, such as user_success,user_tags, and user_parts\nAnd also general stats on the question such as, question_success, all_tags and all_parts.\n\nAnd use these stats to predict the outcome.\nSo basically, if the user has given success values (overall, parts and tags success for the part/tags of the question)...\nAnd the question has its own statistics, (overall question success and, general parts and tags success for the part/tags of the question)...\nThen the a valid prediction is a function of these values.\n\n"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"#read in all the pickled data you need\nimport pickle\n\nwith open('../input/settim/question_success.pickle', 'rb') as handle:\n    question_success = pickle.load(handle)\n    \nwith open('../input/settim/user_success.pickle', 'rb') as handle:\n    user_success = pickle.load(handle)\n    \nwith open('../input/settim/all_parts.pickle', 'rb') as handle:\n    all_parts = pickle.load(handle)\n    \nwith open('../input/settim/all_tags.pickle', 'rb') as handle:\n    all_tags = pickle.load(handle)\n    \nwith open('../input/settim/user_parts.pickle', 'rb') as handle:\n    user_parts = pickle.load(handle)\n    \nwith open('../input/settim/user_tags.pickle', 'rb') as handle:\n    user_tags = pickle.load(handle)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#we need the names (user_id) for the existing users to pull the stats, if that is a user_id for which \n#we have the stats...\nnames=pd.read_csv('../input/settim/userids.csv',usecols=[1])\nnames=names['0']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#we need to pull out the parts and tags related to each question that need be predicted.\n#q will be a simple dataframe of questions and their associated part and tags...\n\ndtypes={'part':'int8','question_id':'int16'}\nq=pd.read_csv('../input/riiid-test-answer-prediction/questions.csv',usecols=[0,3,4]) #this is the original questions if need to check...\n\nq.loc[10033,'tags']='-1'   #that is for the one question without a tag...\ntags_list = [list(map(int,x.split())) for x in q.tags.values]   #now this makes a list of tags in q,, to be used for taganalysis\nq['tags'] = tags_list  #now tags are nothing but a list of integers\nq=q.rename(columns={'question_id':'content_id'})\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def riidpredictor(dataframe):             \n    #this predictor iterates over all the lines of the test data, one by one,\n    #pulls the stats of the user if the user_id within names\n    #and takes a simple median as a prediction...\n    \n    #watch, how the results list is being populated, which will include the available prediction canditates\n    #each prediction candidate, is a function of the known stats, of the question and its tags, and parts\n    #as well as the users success.\n    \n    \n    for row in dataframe.itertuples(): #iterates over rows of test dataframe\n\n        tags=q.loc[row.content_id]['tags']  #pulls out relevant tags for the question of current row\n        part=q.loc[row.content_id]['part']  #pulls out the parts\n        user=int(row.user_id)               #pulss out the user\n        results=[]                          #initializes the results list\n\n        q_success=question_success['mean'][row.content_id]              #this is the simple question success\n        \n        if user not in names.values:                       #check if the user in existing names\n            results.append(q_success)                      #if not, add existing simple question_success to the list\n        else: \n            initial_success=user_success['mean'][user]     # if user already in the names\n            genel_success=q_success + (initial_success - .626)  #project general question_success to the user_succes\n                                           #main idea: if the user is xx% above the overall success rate, than the user\n                                           # will be xx% above question_success (.626 is a close figure to overall success rate)\n            results.append(genel_success)  #use this stats in the results list.\n\n            if (user,part) in user_parts['mean'].keys():  #check if the user has already answered question in this part\n                uparts=user_parts['mean'][(user,part)]    # if yes, use user's part success\n                results.append(uparts)\n\n                aparts=all_parts['mean'][part]              #this is the general parts success\n                aparts_touser=q_success + (uparts - aparts) #here the idea is to produce another metric for the prediction, namely:\n                                                            #if the user is xx%above overall parts'success, the she/he will be \n                                                            # xx% above overall question success\n                \n                results.append(aparts_touser)               #add this also the the prediction candidates...\n                            #at this point we have 3 numbers in the results (if user in already seen names)\n\n            if tags[0]!=-1:                                 #a simple check for the content_id: 10033\n                for tag in tags:                            #which I have tagged with -1 (I know, not very efficient..\n                                                            #to check this in every iteration but, here it is//)\n                        \n                    if (user,tag) in user_tags['mean'].keys():  #again the idea is, if there is a user,tag success\n                        utag=user_tags['mean'][(user,tag)]      #use it in your predictions\n                        results.append(utag)\n\n                        atag=all_tags['mean'][tag]              #also with the same analysis of above as in parts\n                        atag_touser=q_success + (utag - atag)   #if the user is more successful in that certain tag of the question\n                                                                #the tag predictor says, she/he will be that amount better\n                                                                #in that specific question\n                        results.append(atag_touser)\n\n\n\n        prediction= (q_success + np.median(results)) / 2   #one thing that is observed: question success has less variation\n                                                           #than user success values...\n                                                           #this averaging emphasizes the question success\n        prediction=min(max(prediction,0.01),0.99)       #revised calculations for tags and parts above, make it possible to\n                                                        #see values sucs as 1,001 or -0.001\n                                                        #this line squeezes all within prediction limits...\n\n        dataframe.loc[row.Index,'answered_correctly']=prediction  #AND THAT IS IT....\n\n        \n    return dataframe\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import riiideducation\n\nenv = riiideducation.make_env()\niter_test = env.iter_test()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"prior_test_df = None","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for (test_df, sample_prediction_df) in iter_test:  #MIGHT BE BETTER TO CHECK FIRST THE riidpredictor function above\n                                                   #merge the prior test frame with questinons to add part and tags for each\n                                                   #question...\n                                                   #using prior test frame to update stats, we will ise in the riidpredictor\n                \n    if (prior_test_df is not None): \n        \n        prior_test_df['answered_correctly'] = eval(test_df['prior_group_answers_correct'].iloc[0])\n        del prior_test_df['prior_group_answers_correct']\n        \n\n    \n        prior_test_df=prior_test_df.reset_index().merge(q, how=\"left\",on='content_id')\n        \n        \n        for line in prior_test_df.itertuples():\n            if line.content_type_id!=0: \n                continue\n                \n            #for question_success:\n            if line.content_id in question_success['mean']: \n                question_success['mean'][line.content_id]=(question_success['count'][line.content_id] * question_success['mean'][line.content_id] + line.answered_correctly)/(question_success['count'][line.content_id]+1)\n                question_success['count'][line.content_id]+=1\n            else:\n                question_success['mean'][line.content_id]=line.answered_correctly\n                question_success['count'][line.content_id]=1\n\n                \n            #for user_success:\n            if line.user_id in user_success['mean']:\n                user_success['mean'][line.user_id]=(user_success['count'][line.user_id] * user_success['mean'][line.user_id] + line.answered_correctly)/(user_success['count'][line.user_id]+1)\n                user_success['count'][line.user_id]+=1\n            else:\n                user_success['mean'][line.user_id]=line.answered_correctly\n                user_success['count'][line.user_id]=1\n                \n            \n            #for user_parts:\n            if (line.user_id,line.part) in user_parts['mean']:\n                user_parts['mean'][(line.user_id,line.part)]=(user_parts['count'][(line.user_id,line.part)] * user_parts['mean'][(line.user_id,line.part)] + line.answered_correctly)/(user_parts['count'][(line.user_id,line.part)]+1)\n                user_parts['count'][(line.user_id,line.part)]+=1\n            else:\n                user_parts['mean'][(line.user_id,line.part)]=line.answered_correctly\n                user_parts['count'][(line.user_id,line.part)]=1\n        \n            #for all_parts:\n            if line.part in all_parts['mean']:\n                all_parts['mean'][line.part]=(all_parts['count'][line.part] * all_parts['mean'][line.part] + line.answered_correctly)/(all_parts['count'][line.part]+1)\n                all_parts['count'][(line.part)]+=1\n            else:\n                all_parts['mean'][line.part]=line.answered_correctly\n                all_parts['count'][line.part]=1\n                \n                \n            #tags analysis\n            if line.tags[0]!=-1:\n                for tag in line.tags: \n                    \n                    #for user_tags:\n                    if (line.user_id,tag) in user_tags['mean']:\n                        user_tags['mean'][(line.user_id,tag)]=(user_tags['count'][(line.user_id,tag)] * user_tags['mean'][(line.user_id,tag)] + line.answered_correctly)/(user_tags['count'][(line.user_id,tag)]+1)\n                        user_tags['count'][(line.user_id,tag)]+=1\n                    else:\n                        user_tags['mean'][(line.user_id,tag)]=line.answered_correctly\n                        user_tags['count'][(line.user_id,tag)]=1\n                        \n                    #for all_tags:\n                    if tag in all_tags['mean']:\n                        all_tags['mean'][tag]=(all_tags['count'][tag] * all_tags['mean'][tag] + line.answered_correctly)/(all_tags['count'][tag]+1)\n                        all_tags['count'][tag]+=1\n                    else:\n                        all_tags['mean'][tag]=line.answered_correctly\n                        all_tags['count'][tag]=1\n                        \n            #also we need to update names\n            if line.user_id not in names.values:\n                names.loc[names.index.max()+1] =line.user_id\n        \n    \n    prior_test_df = test_df[['row_id','user_id','content_id','content_type_id','prior_group_answers_correct']].copy()\n    \n    test_df = test_df[test_df['content_type_id'] == 0].reset_index(drop=True)\n    results=riidpredictor(test_df)\n    env.predict(results[['row_id', 'answered_correctly']])","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}