konstantgr/themisto huggingface dataset:
cv = CountVectorizer(tokenizer=tokenize_py, lowercase=False).fit(train_features['text'].values)
tf_transformer = TfidfTransformer().fit(cv.transform(train_features['text'].values))
clf = MultinomialNB().fit(tf_transformer.transform(cv.transform(train_features['text'].values)), 
                          np.vectorize(class_map.get)(df[y_column].values).squeeze())
cv = CountVectorizer(tokenizer=tokenize_py, lowercase=False).fit(train_features['text'].values)
tf_transformer = TfidfTransformer().fit(cv.transform(train_features['text'].values))
clf = MultinomialNB().fit(tf_transformer.transform(cv.transform(train_features['text'].values)), 
                          np.vectorize(class_map.get)(train_features[y_column].values).squeeze())
nb_prd = clf.predict_proba(tf_transformer.transform(cv.transform(validation_features['text'].values)))
nb_prd.shape
pd.DataFrame(nb_prd)
pd.DataFrame(nb_prd, columns=[f'nb_{i}' for i in range(10)])
def prepare_dataset_RF(df):
    y_multi = df[y_columns].values
    y_primary = np.vectorize(class_map.get)(df[y_column].values)
    X_numeric = df[X_columns - X_columns_text]
    X_text = df[X_columns_text]
    X_numeric_texts = X_text.applymap(lambda x: len(x) if not isinstance(x, int) else x)
    X_nbed_text = clf.predict_proba(tf_transformer.transform(cv.transform(df['text'].values)))
    X = pd.merge(X_numeric, X_numeric_texts, left_index=True, right_index=True)
    X = pd.merge(X, pd.DataFrame(X_nbed_text, columns=[f'nb_{i}' for i in range(10)]), 
                 left_index=True, right_index=True)
    return X, y_multi, y_primary
rfclf = RandomForestClassifier(min_samples_leaf=10, max_depth=20, )
rfclf = RandomForestClassifier(min_samples_leaf=10, max_depth=30, )
rfclf = RandomForestClassifier(min_samples_leaf=5, max_depth=30, )
train_features['comment']
train_features['comment_only']
train_features['text'][1]
tokenize_py([train_features['text'][1]])
cv_ft = CountVectorizer(lowercase=False).fit(train_features['text'].values)
tf_transformer_ft = TfidfTransformer().fit(cv_ft.transform(train_features['text'].values))
clf_ft = MultinomialNB().fit(tf_transformer_ft.transform(cv_ft.transform(train_features['text'].values)), 
                          np.vectorize(class_map.get)(train_features[y_column].values).squeeze())
[' \n '.concatenate(i) for i in train_features['text'].values]
[' \n '.join(i) for i in train_features['text'].values]
cv_ft = CountVectorizer(lowercase=False).fit([' \n '.join(i) for i in train_features['text'].values])
tf_transformer_ft = TfidfTransformer().fit(cv_ft.transform(train_features['text'].values))
clf_ft = MultinomialNB().fit(tf_transformer_ft.transform(cv_ft.transform(train_features['text'].values)), 
                          np.vectorize(class_map.get)(train_features[y_column].values).squeeze())
cv_ft = CountVectorizer(lowercase=False).fit([' \n '.join(i) for i in train_features['text'].values])
tf_transformer_ft = TfidfTransformer().fit(cv_ft.transform([' \n '.join(i) for i in train_features['text'].values]))
clf_ft = MultinomialNB().fit(tf_transformer_ft.transform(cv_ft.transform([' \n '.join(i) for i in train_features['text'].values])), 
                          np.vectorize(class_map.get)(train_features[y_column].values).squeeze())
def prepare_dataset_RF(df):
    y_multi = df[y_columns].values
    y_primary = np.vectorize(class_map.get)(df[y_column].values)
    X_numeric = df[X_columns - X_columns_text]
    X_text = df[X_columns_text]
    X_numeric_texts = X_text.applymap(lambda x: len(x) if not isinstance(x, int) else x)
    
    X_nbed_text = clf.predict_proba(tf_transformer.transform(cv.transform(df['text'].values)))
    X_nbed_text_full = clf.predict_proba(tf_transformer.transform(cv.transform([' \n '.join(i) for i in train_features['text'].values])))
    
    X = pd.merge(X_numeric, X_numeric_texts, left_index=True, right_index=True)
    X = pd.merge(X, pd.DataFrame(X_nbed_text, columns=[f'nb_{i}' for i in range(10)]), 
                 left_index=True, right_index=True)
    X = pd.merge(X, pd.DataFrame(X_nbed_text_full, columns=[f'nb_full_{i}' for i in range(10)]), 
                 left_index=True, right_index=True)
    return X, y_multi, y_primary
train_features['comment'][1]
cv_c = CountVectorizer(tokenizer=tokenize_py, lowercase=False).fit(train_features['comment'].values)
tf_transformer_c = TfidfTransformer().fit(cv_c.transform(train_features['comment'].values))
clf_c = MultinomialNB().fit(tf_transformer_c.transform(cv_c.transform(train_features['comment'].values)), 
                          np.vectorize(class_map.get)(train_features[y_column].values).squeeze())
cv_c = CountVectorizer(lowercase=False).fit(train_features['comment'].values)
tf_transformer_c = TfidfTransformer().fit(cv_c.transform(train_features['comment'].values))
clf_c = MultinomialNB().fit(tf_transformer_c.transform(cv_c.transform(train_features['comment'].values)), 
                          np.vectorize(class_map.get)(train_features[y_column].values).squeeze())
cv_c = CountVectorizer(lowercase=False).fit([' \n '.join(i) for i in train_features['text'].values])
tf_transformer_c = TfidfTransformer().fit(cv_c.transform([' \n '.join(i) for i in train_features['text'].values]))
clf_c = MultinomialNB().fit(tf_transformer_c.transform(cv_c.transform([' \n '.join(i) for i in train_features['text'].values])), 
                          np.vectorize(class_map.get)(train_features[y_column].values).squeeze())
def prepare_dataset_RF(df):
    y_multi = df[y_columns].values
    y_primary = np.vectorize(class_map.get)(df[y_column].values)
    X_numeric = df[X_columns - X_columns_text]
    X_text = df[X_columns_text]
    X_numeric_texts = X_text.applymap(lambda x: len(x) if not isinstance(x, int) else x)
    
    X_nbed_text = clf.predict_proba(tf_transformer.transform(cv.transform(df['text'].values)))
    X_nbed_text_full = clf_ft.predict_proba(tf_transformer_ft.transform(cv_ft.transform([' \n '.join(i) for i in df['text'].values])))
    X_nbed_comment = clf_c.predict_proba(tf_transformer_c.transform(cv_c.transform([' \n '.join(i) for i in df['comment'].values])))
    
    X = pd.merge(X_numeric, X_numeric_texts, left_index=True, right_index=True)
    X = pd.merge(X, pd.DataFrame(X_nbed_text, columns=[f'nb_{i}' for i in range(10)]), 
                 left_index=True, right_index=True)
    X = pd.merge(X, pd.DataFrame(X_nbed_text_full, columns=[f'nb_full_{i}' for i in range(10)]), 
                 left_index=True, right_index=True)
    X = pd.merge(X, pd.DataFrame(X_nbed_comment, columns=[f'nb_full_{i}' for i in range(10)]), 
                 left_index=True, right_index=True)
    return X, y_multi, y_primary
rfclf = RandomForestClassifier(min_samples_leaf=1, max_depth=30, )
rfclf = RandomForestClassifier(min_samples_leaf=1, max_depth=40, )
rfclf = RandomForestClassifier(min_samples_leaf=1, max_depth=30)
rfclf = RandomForestClassifier(min_samples_leaf=1, max_depth=20)
X_test, y_test_multi, y_test_primary = prepare_dataset_RF(test_features)
def prepare_X(df):
    X_numeric = df[X_columns - X_columns_text]
    X_text = df[X_columns_text]
    X_numeric_texts = X_text.applymap(lambda x: len(x) if not isinstance(x, int) else x)
    
    X_nbed_text = clf.predict_proba(tf_transformer.transform(cv.transform(df['text'].values)))
    X_nbed_text_full = clf_ft.predict_proba(tf_transformer_ft.transform(cv_ft.transform([' \n '.join(i) for i in df['text'].values])))
    X_nbed_comment = clf_c.predict_proba(tf_transformer_c.transform(cv_c.transform([' \n '.join(i) for i in df['comment'].values])))
    
    X = pd.merge(X_numeric, X_numeric_texts, left_index=True, right_index=True)
    X = pd.merge(X, pd.DataFrame(X_nbed_text, columns=[f'nb_{i}' for i in range(10)]), 
                 left_index=True, right_index=True)
    X = pd.merge(X, pd.DataFrame(X_nbed_text_full, columns=[f'nb_full_{i}' for i in range(10)]), 
                 left_index=True, right_index=True)
    X = pd.merge(X, pd.DataFrame(X_nbed_comment, columns=[f'nb_full_{i}' for i in range(10)]), 
                 left_index=True, right_index=True)
    return X

def prepare_y(df):
    y_multi = df[y_columns].values
    y_primary = np.vectorize(class_map.get)(df[y_column].values)
    return y_multi, y_primary
set(train_features.filename) & set(validation_features.filename) #hmmm...
# The targets are set in stone
y_columns = ['load_data', 'helper_functions', 'data_preprocessing', 'data_exploration', 
             'modelling', 'prediction', 'evaluation',
             'result_visualization', 'save_results', 'comment_only']
y_column = ['primary_label']
# Config of the data types defining how to further process it for different trainings
X_columns = set(train_features.columns) - set(y_column) - set(y_columns) - {'filename', 'cell_type'}
X_columns_text = {'packages_info', 'code_line_after', 'code_line_before', 'text', 'comment', 'markdown_heading'}
class_map = {k: i for i, k in enumerate(train_features.primary_label.unique())}
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
import numpy as np
from tokenize import generate_tokens
class Readliner:
    def __init__(self, text_lines):
        self.text_lines = text_lines
        self.i = 0
        
    def __call__(self):
        if self.i < len(self):
            ctxt = self.text_lines[self.i]
            self.i += 1
            return ctxt
        return ''
    
    def __len__(self):
        return len(self.text_lines)

def tokenize_py(txt):
    try:
        return [i.string for i in generate_tokens(Readliner(txt))]
    except:
        return ['Fehler']
# comments tokenized with builtin python tokenizer
cv = CountVectorizer(tokenizer=tokenize_py, lowercase=False).fit(train_features['text'].values)
tf_transformer = TfidfTransformer().fit(cv.transform(train_features['text'].values))
clf = MultinomialNB().fit(tf_transformer.transform(cv.transform(train_features['text'].values)), 
                          np.vectorize(class_map.get)(train_features[y_column].values).squeeze())
# code tokenized with builtin sklearn tokenizer
cv_ft = CountVectorizer(lowercase=False).fit([' \n '.join(i) for i in train_features['text'].values])
tf_transformer_ft = TfidfTransformer().fit(cv_ft.transform([' \n '.join(i) for i in train_features['text'].values]))
clf_ft = MultinomialNB().fit(tf_transformer_ft.transform(cv_ft.transform([' \n '.join(i) for i in train_features['text'].values])), 
                          np.vectorize(class_map.get)(train_features[y_column].values).squeeze())
# comments tokenized with the builtin sklearn tokenizer
cv_c = CountVectorizer(lowercase=False).fit([' \n '.join(i) for i in train_features['text'].values])
tf_transformer_c = TfidfTransformer().fit(cv_c.transform([' \n '.join(i) for i in train_features['text'].values]))
clf_c = MultinomialNB().fit(tf_transformer_c.transform(cv_c.transform([' \n '.join(i) for i in train_features['text'].values])), 
                          np.vectorize(class_map.get)(train_features[y_column].values).squeeze())
X_train = prepare_X(train_features)
y_train_multi, y_train_primary = prepare_y(train_features)
X_val = prepare_X(validation_features)
y_val_multi, y_val_primary = prepare_y(validation_features)
rfclf = RandomForestClassifier(min_samples_leaf=1, max_depth=20).fit(X_train, y_train_primary);
f1_score(y_train_primary, rfclf.predict(X_train), average=None).mean()
rfclf = RandomForestClassifier(min_samples_leaf=5, max_depth=20).fit(X_train, y_train_primary);
rfclf = RandomForestClassifier(min_samples_leaf=10, max_depth=20).fit(X_train, y_train_primary);
rfclf = RandomForestClassifier(min_samples_leaf=15, max_depth=20).fit(X_train, y_train_primary);
X_test = prepare_X(test_features)
p_test = rfclf.predict(prepare_X(test_features))
f1_score(y_test_primary, rfclf.predict(X_val), average=None)
# code tokenized with builtin python tokenizer
cv = CountVectorizer(tokenizer=tokenize_py, lowercase=False).fit(train_features['text'].values)
tf_transformer = TfidfTransformer().fit(cv.transform(train_features['text'].values))
clf = MultinomialNB().fit(tf_transformer.transform(cv.transform(train_features['text'].values)), 
                          np.vectorize(class_map.get)(train_features[y_column].values).squeeze())
data_path = "data/task1/jetnet_logs.txt"

f = open(data_path, "r")
print(f.read())
data_path = "data/task1/jetnet_logs.txt"

f = open(data_path, "r")
print(f.readline())
f.readline()
l = f.readline()
split(l, ' ')
l.split(' ')
l.split('->')
l.split('(-+)>')
l.split('-+>')
l.split('-*>')
def parse(log):
    name = log.split()[0][:-1]
    print(name)
parse(l)
def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2]
    print(name, log)
def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    print(name, log)
import re

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    print(name, log)
import re

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    print(name)
    print(log)
import re

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    
    actions = []
    
    for s in log:
        action_name = s.split()[0]
        time  = s[len(action_name) + 1:]
        actions.append((action_name, time))
    print(name)
    print(actions)
import re

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    
    actions = []
    
    for s in log:
        action_name = s.split()[0]
        time  = s[len(action_name) + 1:]
        actions.append((action_name, time))
    print(name)
    print(*actions)
import re
from datetime import datetime

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    
    actions = []
    
    for s in log:
        action_name = s.split()[0]
        time  = s[len(action_name) + 1:]
        
        datetime.strptime(time, '%d/%m/%y | %H:%M:%S')
        actions.append((action_name, time))
        
    
    print(name)
    print(*actions)
import re
from datetime import datetime

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    
    actions = []
    
    for s in log:
        action_name = s.split()[0]
        time  = s[len(action_name) + 1:]
        
        datetime.strptime(time, '(%d/%m/%y | %H:%M:%S)')
        actions.append((action_name, time))
        
    
    print(name)
    print(*actions)
import re
from datetime import datetime

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    
    actions = []
    
    for s in log:
        action_name = s.split()[0]
        time  = s[len(action_name) + 1:]
        
        datetime.strptime(time.strip(), '(%d/%m/%y | %H:%M:%S)')
        actions.append((action_name, time))
        
    
    print(name)
    print(*actions)
import re
from datetime import datetime

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    
    actions = []
    
    for s in log:
        action_name = s.split()[0]
        time  = s[len(action_name) + 1:]
        
        time = datetime.strptime(time.strip(), '(%d/%m/%y | %H:%M:%S)')
        actions.append((action_name, time))
        
    
    print(name)
    print(*actions)
import re
from datetime import datetime

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    
    actions = []
    
    for s in log:
        action_name = s.split()[0]
        time  = s[len(action_name) + 1:]
        
        time = datetime.strptime(time.strip(), '(%d/%m/%y | %H:%M:%S)')
        actions.append((action_name, time))
    return name, actions
l = f.readline()
print(l)
parse(l)
import re
from datetime import datetime

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    
    actions = []
    
    for s in log:
        if (len(log.strip()) > 0)
        action_name = s.split()[0]
        time  = s[len(action_name) + 1:]
        
        time = datetime.strptime(time.strip(), '(%d/%m/%y | %H:%M:%S)')
        actions.append((action_name, time))
    return name, actions
import re
from datetime import datetime

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    
    actions = []
    
    for s in log:
        if (len(log.strip()) > 0):
            action_name = s.split()[0]
            time  = s[len(action_name) + 1:]

            time = datetime.strptime(time.strip(), '(%d/%m/%y | %H:%M:%S)')
            actions.append((action_name, time))
    return name, actions
import re
from datetime import datetime

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    
    actions = []
    
    for s in log:
        if (len(s.strip()) > 0):
            action_name = s.split()[0]
            time  = s[len(action_name) + 1:]

            time = datetime.strptime(time.strip(), '(%d/%m/%y | %H:%M:%S)')
            actions.append((action_name, time))
    return name, actions
data_path = "data/task1/jetnet_logs.txt"

f = open(data_path, "r")
lines = f.readlines()
parsed = map(parse, lines)
len(parsed)
lines = f.readlines()
parsed = list(map(parse, lines))
len(parsed)
f.readlines()
import re
from datetime import datetime

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    
    actions = []
    
    for s in log:
        if (len(s.strip()) > 0):
            action_name = s.split()[0]
            time  = s[len(action_name):]

            time = datetime.strptime(time.strip(), '(%d/%m/%y | %H:%M:%S)')
            actions.append((action_name, time))
    return name, actions
import re
from datetime import datetime

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    
    actions = []
    
    for s in log:
        print(s)
        if (len(s.strip()) > 0):
            action_name = s.split()[0]
            time  = s[len(action_name):]

            time = datetime.strptime(time.strip(), '(%d/%m/%y | %H:%M:%S)')
            actions.append((action_name, time))
    return name, actions
import re
from datetime import datetime

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    
    actions = []
    
    for s in log:
        s = s.strip()
        if (len(s) > 0):
            action_name = s.split()[0]
            time  = s[len(action_name):]

            time = datetime.strptime(time.strip(), '(%d/%m/%y | %H:%M:%S)')
            actions.append((action_name, time))
    return name, actions
import re
from datetime import datetime

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    
    actions = []
    
    for s in log:
        s = s.strip()
        print(s)
        if (len(s) > 0):
            action_name = s.split()[0]
            time  = s[len(action_name):]

            time = datetime.strptime(time.strip(), '(%d/%m/%y | %H:%M:%S)')
            actions.append((action_name, time))
    return name, actions
import re
from datetime import datetime

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    
    actions = []
    
    for s in log:
        s = s.strip()
        print(s)
        if (len(s) > 0):
            action_name = s.split()[0]
            time = s[len(action_name):].strip()
            if time[0] != '(':
                time = '(' + time
            
            time = datetime.strptime(time.strip(), '(%d/%m/%y | %H:%M:%S)')
            actions.append((action_name, time))
    return name, actions
import re
from datetime import datetime

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    
    actions = []
    
    for s in log:
        s = s.strip()
        print(s)
        if (len(s) > 0):
            action_name = s.split()[0]
            time = s[len(action_name):].strip()
            if time[0] != '(':
                time = '(' + time
            if time == "(null)":
                time = '(01/01/01 | 00:00:00)'
            
            time = datetime.strptime(time.strip(), '(%d/%m/%y | %H:%M:%S)')
            actions.append((action_name, time))
    return name, actions
data_path = "data/task1/jetnet_logs.txt"

f = open(data_path, "r")
lines = f.readlines()
len(lines)
data_path = "data/task1/jetnet_logs.txt"

f = open(data_path, "r")
lines = f.readlines()
len(lines)
lines2 = []
for line in lines:
    ind = line[1:].find('@')
    if ind == -1:
        lines2.append(line)
    else:
        ind += 1
        lines2.append(line[:ind])
        lines2.append(line[:ind])

lines = lines2
len(lines)
parsed = list(map(parse, lines))
len(parsed)
import re
from datetime import datetime

def parse(log):
    name = log.split()[0][:-1]
    log = log[len(name) + 2:]
    log = re.split('-+>', log)
    
    actions = []
    
    for s in log:
        s = s.strip()
        if (len(s) > 0):
            action_name = s.split()[0]
            time = s[len(action_name):].strip()
            if time[0] != '(':
                time = '(' + time
            if time == "(null)":
                time = '(01/01/01 | 00:00:00)'
            
            time = datetime.strptime(time.strip(), '(%d/%m/%y | %H:%M:%S)')
            actions.append((action_name, time))
    return name, actions
parsed[0], lines[0]
parsed[-123], lines[-123]
parsed[-2], lines[-2]
parsed[-1], lines[-1]
lines2 = []
for line in lines:
    assert line.find('@') <= 2
    ind = line[1:].find('@')
    if ind == -1:
        lines2.append(line)
    else:
        ind += 1
        lines2.append(line[:ind])
        lines2.append(line[:ind])

lines = lines2
len(lines)
lines2 = []
for line in lines:
    assert line.count('@') <= 2
    ind = line[1:].find('@')
    if ind == -1:
        lines2.append(line)
    else:
        ind += 1
        lines2.append(line[:ind])
        lines2.append(line[:ind])

lines = lines2
len(lines)
def split_lines(line):
    ind = line[1:].find('@')
    if ind == -1:
        return line
    else:
        ind += 1
        return [line[:ind]] + split_lines(line[ind:])

lines2 = []
for line in lines:
    for l in split(lines):
        lines2.append(l)
    
lines = lines2
len(lines)
def split_lines(line):
    ind = line[1:].find('@')
    if ind == -1:
        return line
    else:
        ind += 1
        return [line[:ind]] + split_lines(line[ind:])

lines2 = []
for line in lines:
    for l in split_line(lines):
        lines2.append(l)
    
lines = lines2
len(lines)
def split_lines(line):
    ind = line[1:].find('@')
    if ind == -1:
        return line
    else:
        ind += 1
        return [line[:ind]] + split_lines(line[ind:])

lines2 = []
for line in lines:
    for l in split_lines(lines):
        lines2.append(l)
    
lines = lines2
len(lines)
def split_lines(line):
    ind = line[1:].find('@')
    if ind == -1:
        return line
    else:
        ind += 1
        return [line[:ind]] + split_lines(line[ind:])

lines2 = []
for line in lines:
    for l in split_lines(line):
        lines2.append(l)
    
lines = lines2
len(lines)
def split_lines(line):
    ind = line[1:].find('@')
    if ind == -1:
        return [line]
    else:
        ind += 1
        return [line[:ind]] + split_lines(line[ind:])

lines2 = []
for line in lines:
    for l in split_lines(line):
        lines2.append(l)
    
lines = lines2
len(lines)
import pandas as pd

df = pd.DataFrame({'user_id' : [], 'session_num' : [], 'action_time' : [], 'action_name': []})

for (name, actions) in parsed:
    curr_session = 0
    if name in session_num:
        curr_session = session_num[name] + 1
    session_num[name] = curr_session + 1
    
    for (action_name, time) in actions:
        df.append({
            'user_id' : name, 
            "session_num": curr_session, 
            "action_time": time, 
            "action_name": action_name}, ignore_index=True)

df.head()
session_num = dict()