HW5 -- Artificial Artificial Intelligence

In [1]:
import pandas as pd
import numpy as np

neg = pd.read_csv('AMT_neg.csv')
pos = pd.read_csv('AMT_pos.csv')

Initial EDA

In [5]:
neg[:3]
Out[5]:
HITId HITTypeId Title Description Keywords Reward CreationTime MaxAssignments RequesterAnnotation AssignmentDurationInSeconds ... RejectionTime RequesterFeedback WorkTimeInSeconds LifetimeApprovalRate Last30DaysApprovalRate Last7DaysApprovalRate Input.text Answer.sentiment.label Approve Reject
0 3IQ9O0AYW6ZI3GD740H32KGG2SWITJ 3N0K7CX2I27L2NR2L8D93MF8LIRA5J Sentiment analysis Sentiment analysis sentiment, text $0.02 Fri Nov 01 12:08:17 PDT 2019 3 BatchId:3821423;OriginalHitTemplateId:928390909; 10800 ... NaN NaN 44 0% (0/0) 0% (0/0) 0% (0/0) Missed Opportunity\nI had been very excited to... Neutral NaN NaN
1 3IQ9O0AYW6ZI3GD740H32KGG2SWITJ 3N0K7CX2I27L2NR2L8D93MF8LIRA5J Sentiment analysis Sentiment analysis sentiment, text $0.02 Fri Nov 01 12:08:17 PDT 2019 3 BatchId:3821423;OriginalHitTemplateId:928390909; 10800 ... NaN NaN 7 0% (0/0) 0% (0/0) 0% (0/0) Missed Opportunity\nI had been very excited to... Negative NaN NaN
2 3IQ9O0AYW6ZI3GD740H32KGG2SWITJ 3N0K7CX2I27L2NR2L8D93MF8LIRA5J Sentiment analysis Sentiment analysis sentiment, text $0.02 Fri Nov 01 12:08:17 PDT 2019 3 BatchId:3821423;OriginalHitTemplateId:928390909; 10800 ... NaN NaN 449 0% (0/0) 0% (0/0) 0% (0/0) Missed Opportunity\nI had been very excited to... Positive NaN NaN

3 rows × 31 columns

In [6]:
pos[:3]
Out[6]:
HITId HITTypeId Title Description Keywords Reward CreationTime MaxAssignments RequesterAnnotation AssignmentDurationInSeconds ... RejectionTime RequesterFeedback WorkTimeInSeconds LifetimeApprovalRate Last30DaysApprovalRate Last7DaysApprovalRate Input.text Answer.sentiment.label Approve Reject
0 3VMV5CHJZ8F47P7CECH0H830NF4GTP 3N0K7CX2I27L2NR2L8D93MF8LIRA5J Sentiment analysis Sentiment analysis sentiment, text $0.02 Fri Nov 01 12:11:19 PDT 2019 3 BatchId:3821427;OriginalHitTemplateId:928390909; 10800 ... NaN NaN 355 0% (0/0) 0% (0/0) 0% (0/0) funny like a clown\nGreetings again from the d... Positive NaN NaN
1 3VMV5CHJZ8F47P7CECH0H830NF4GTP 3N0K7CX2I27L2NR2L8D93MF8LIRA5J Sentiment analysis Sentiment analysis sentiment, text $0.02 Fri Nov 01 12:11:19 PDT 2019 3 BatchId:3821427;OriginalHitTemplateId:928390909; 10800 ... NaN NaN 487 0% (0/0) 0% (0/0) 0% (0/0) funny like a clown\nGreetings again from the d... Neutral NaN NaN
2 3VMV5CHJZ8F47P7CECH0H830NF4GTP 3N0K7CX2I27L2NR2L8D93MF8LIRA5J Sentiment analysis Sentiment analysis sentiment, text $0.02 Fri Nov 01 12:11:19 PDT 2019 3 BatchId:3821427;OriginalHitTemplateId:928390909; 10800 ... NaN NaN 1052 0% (0/0) 0% (0/0) 0% (0/0) funny like a clown\nGreetings again from the d... Positive NaN NaN

3 rows × 31 columns

In [7]:
neg.columns.tolist()
Out[7]:
['HITId',
 'HITTypeId',
 'Title',
 'Description',
 'Keywords',
 'Reward',
 'CreationTime',
 'MaxAssignments',
 'RequesterAnnotation',
 'AssignmentDurationInSeconds',
 'AutoApprovalDelayInSeconds',
 'Expiration',
 'NumberOfSimilarHITs',
 'LifetimeInSeconds',
 'AssignmentId',
 'WorkerId',
 'AssignmentStatus',
 'AcceptTime',
 'SubmitTime',
 'AutoApprovalTime',
 'ApprovalTime',
 'RejectionTime',
 'RequesterFeedback',
 'WorkTimeInSeconds',
 'LifetimeApprovalRate',
 'Last30DaysApprovalRate',
 'Last7DaysApprovalRate',
 'Input.text',
 'Answer.sentiment.label',
 'Approve',
 'Reject']

How many unique turkers worked on each dataframe?

In [31]:
def get_unique(df, column):
    unique = np.unique(df[column], return_counts=True)
    df = pd.DataFrame(zip(unique[0], unique[1]))
    return len(unique[0]), unique, df

num_neg, unique_neg, u_neg_df = get_unique(neg, 'WorkerId')    
num_pos, unique_pos, u_pos_df = get_unique(pos, 'WorkerId')

print(num_neg, 'Turkers worked on NEG batch')
print(num_pos, 'Turkers worked on POS batch')
53 Turkers worked on NEG batch
38 Turkers worked on POS batch

How many HITS did each unique turker do?

In [32]:
u_neg_df.plot(kind='bar',x=0,y=1)
Out[32]:
<matplotlib.axes._subplots.AxesSubplot at 0x11cdcb978>
In [33]:
u_pos_df.plot(kind='bar',x=0,y=1)
Out[33]:
<matplotlib.axes._subplots.AxesSubplot at 0x11c5d1748>

What's the max and min HIT for unique turkers

In [39]:
print('For {}, the min was: {} and the max was: {}'.format('neg', unique_neg[1].min(), unique_neg[1].max())) 
print('For {}, the min was: {} and the max was: {}'.format('pos', unique_pos[1].min(), unique_pos[1].max())) 
For neg, the min was: 1 and the max was: 37
For pos, the min was: 1 and the max was: 40

Did a specitic Sentiment take longer for turkers to assess?

In [20]:
import seaborn as sns
import matplotlib.pyplot as plt
sns.catplot(x="Answer.sentiment.label", 
            y="WorkTimeInSeconds", 
            kind="bar", 
            order=['Negative', 'Neutral', 'Positive'], 
            data=neg);
plt.title('Negative')
Out[20]:
Text(0.5, 1, 'Negative')
In [19]:
sns.catplot(x="Answer.sentiment.label", 
            y="WorkTimeInSeconds", 
            kind="bar", 
            order=['Negative', 'Neutral', 'Positive'], 
            data=pos)
plt.title('Positive')
Out[19]:
Text(0.5, 1, 'Positive')

How many turkers had less than 10 second response time?

In [44]:
response_time = neg[neg['WorkTimeInSeconds'] < 10]
response_time_check = neg[neg['WorkTimeInSeconds'] > 10]
In [45]:
len(response_time)
Out[45]:
48
In [46]:
len(response_time_check)
Out[46]:
312

Checking for potential bots

Did anyone have a consistent average low response time?

In [74]:
count = pos.groupby(['WorkerId'])['HITId'].count()
work_time = pos.groupby(['WorkerId'])['WorkTimeInSeconds'].mean()
new_df = pd.DataFrame([work_time, count]).T
new_df[:5]
Out[74]:
WorkTimeInSeconds HITId
WorkerId
A13CLN8L5HFT46 7.230769 13.0
A18WFPSLFV4FKY 47.000000 2.0
A1IQV3QUWRA8G1 22.000000 1.0
A1N1ULK71RHVMM 10.000000 3.0
A1S2MN0E9BHPVA 173.444444 27.0

Did anyone have a consistent average high response time?

In [75]:
new_df['WorkTimeInMin'] = new_df['WorkTimeInSeconds']/60
new_df[:5]
Out[75]:
WorkTimeInSeconds HITId WorkTimeInMin
WorkerId
A13CLN8L5HFT46 7.230769 13.0 0.120513
A18WFPSLFV4FKY 47.000000 2.0 0.783333
A1IQV3QUWRA8G1 22.000000 1.0 0.366667
A1N1ULK71RHVMM 10.000000 3.0 0.166667
A1S2MN0E9BHPVA 173.444444 27.0 2.890741
In [86]:
count = pos.groupby(['WorkerId', 'Answer.sentiment.label'])['Answer.sentiment.label'].count()
# count = pos.groupby(['WorkerId'])['Answer.sentiment.label'].count()
count
Out[86]:
WorkerId        Answer.sentiment.label
A13CLN8L5HFT46  Neutral                    2
                Positive                  11
A18WFPSLFV4FKY  Positive                   2
A1IQV3QUWRA8G1  Positive                   1
A1N1ULK71RHVMM  Negative                   1
                                          ..
AMC42JMQA8A5U   Positive                   1
AO2WNSGOXAX52   Neutral                    3
                Positive                   1
AOMFEAWQHU3D8   Neutral                    1
                Positive                   6
Name: Answer.sentiment.label, Length: 74, dtype: int64

Did anyone answer ONLY pos/neg/neutral?

In [117]:
pnn = pd.DataFrame()
pnn['Neutral'] = pos.groupby('WorkerId')['Answer.sentiment.label'].apply(lambda x: (x=='Neutral').sum())
pnn['Positive'] = pos.groupby('WorkerId')['Answer.sentiment.label'].apply(lambda x: (x=='Positive').sum())
pnn['Negative'] = pos.groupby('WorkerId')['Answer.sentiment.label'].apply(lambda x: (x=='Negative').sum())
pnn['Total'] = pos.groupby('WorkerId')['Answer.sentiment.label'].apply(lambda x: x.count())
pnn[:5]
Out[117]:
Neutral Positive Negative Total
WorkerId
A13CLN8L5HFT46 2 11 0 13
A18WFPSLFV4FKY 0 2 0 2
A1IQV3QUWRA8G1 0 1 0 1
A1N1ULK71RHVMM 0 2 1 3
A1S2MN0E9BHPVA 2 21 4 27

This is getting a little confusing, let's just look at our top performers

In [122]:
top = pnn.sort_values(by=['Total'], ascending=False)
In [123]:
top[:10]
Out[123]:
Neutral Positive Negative Total
WorkerId
A681XM15AN28F 13 20 7 40
A1Y66T7FKJ8PJA 5 23 7 35
A33ENZVC1XB4BA 0 34 0 34
A1S2MN0E9BHPVA 2 21 4 27
A37L5E8MHHQGZM 6 13 3 22
AE03LUY7RH400 4 10 7 21
A2G44A4ZPWRPXU 4 12 2 18
A1YK1IKACUJMV4 0 15 0 15
A3AW887GI0NLKF 3 10 2 15
A3HAEQW13YPT6A 0 14 0 14

Interesting!! Looking from here, we have three workers who ONLY chose positive.

Let's look at their response time to see if we can determine if they are a bot!!

In [130]:
top['Avg_WorkTimeInSeconds'] = pos.groupby('WorkerId')['WorkTimeInSeconds'].apply(lambda x: x.mean())
top['Avg_WorkTimeInMin'] = pos.groupby('WorkerId')['WorkTimeInSeconds'].apply(lambda x: x.mean()/60)
top['Min_WorkTimeInMin'] = pos.groupby('WorkerId')['WorkTimeInSeconds'].apply(lambda x: x.min()/60)
top['Max_WorkTimeInMin'] = pos.groupby('WorkerId')['WorkTimeInSeconds'].apply(lambda x: x.max()/60)
In [131]:
top[:10]
Out[131]:
Neutral Positive Negative Total Avg_WorkTimeInSeconds Avg_WorkTimeInMin Min_WorkTimeInMin Max_WorkTimeInMin
WorkerId
A681XM15AN28F 13 20 7 40 13.575000 0.226250 0.100000 0.833333
A1Y66T7FKJ8PJA 5 23 7 35 695.857143 11.597619 0.216667 22.000000
A33ENZVC1XB4BA 0 34 0 34 366.647059 6.110784 0.616667 9.916667
A1S2MN0E9BHPVA 2 21 4 27 173.444444 2.890741 0.400000 4.983333
A37L5E8MHHQGZM 6 13 3 22 346.272727 5.771212 2.150000 8.283333
AE03LUY7RH400 4 10 7 21 102.238095 1.703968 0.100000 3.433333
A2G44A4ZPWRPXU 4 12 2 18 221.277778 3.687963 0.383333 7.383333
A1YK1IKACUJMV4 0 15 0 15 593.600000 9.893333 1.716667 11.000000
A3AW887GI0NLKF 3 10 2 15 269.400000 4.490000 1.616667 7.216667
A3HAEQW13YPT6A 0 14 0 14 442.928571 7.382143 0.866667 11.100000

Even more interesting! These two don't appear to be bots, based on our current metric which is time variability.

HOWEVER, worker A681XM15AN28F appears to only work for an average of 13 seconds per review which doesn't seem like enough time to read and judge a review...

PART 2: Second submission to AMT

TOO MANY REVIEWERS!

Here is when we realized that doing a kappa score with over 30 individual reviewers would be tricky, so we rusubmitted to AMT and required the turkers to be 'Master' in the hopes that this additional barrier-to-entry would help reduce the amount of turkers working on the project

In [138]:
v2 = pd.read_csv('HW5_amt_v2.csv')
v2[:5]
len(v2)
Out[138]:
293

This time, I didn't separate the df into pos and neg before submitting to AMT, so we have to reimport the labels.

In [136]:
labels = pd.read_csv('all_JK_extremes_labeled.csv')
In [139]:
len(labels)
Out[139]:
98

Oops! That's right, we replicated each review * 3 so three separate people could look at each review

In [160]:
labels2 = labels.append([labels] * 2, ignore_index=True)
In [161]:
len(labels2)
Out[161]:
294
In [162]:
labels2.sort_values(by='0')
Out[162]:
0 PoN
76 #LetRottenTomatoesRotSquad\nI am a simple guy... P
174 #LetRottenTomatoesRotSquad\nI am a simple guy... P
272 #LetRottenTomatoesRotSquad\nI am a simple guy... P
116 A 'Triumph of the Will' for Nihilists\n'Joker... N
18 A 'Triumph of the Will' for Nihilists\n'Joker... N
... ... ...
227 lose of both time and money\nThis was one of ... N
31 lose of both time and money\nThis was one of ... N
207 poor plot\nPoor plot. i find no reason for jo... N
11 poor plot\nPoor plot. i find no reason for jo... N
109 poor plot\nPoor plot. i find no reason for jo... N

294 rows × 2 columns

Shoot! I realized I had to delete some emojis for the csv to be accepted by AMT, so the reviews themselves won't actually be matching... solution: Create two 'for-matching' columns made up of the first 5 words of each review

In [171]:
v2['for_matching'] = v2.apply(lambda x: x['Input.text'].split()[:5], axis=1)
In [172]:
labels2['for_matching'] = labels2.apply(lambda x: x['0'].split()[:5], axis=1)

Annnnnd why did I do that when I could just sort the df and apply the PoN

In [176]:
sorted_labels = labels2.sort_values(by='0')
sorted_labels[:6]
Out[176]:
0 PoN for_matching
76 #LetRottenTomatoesRotSquad\nI am a simple guy... P [#LetRottenTomatoesRotSquad, I, am, a, simple]
174 #LetRottenTomatoesRotSquad\nI am a simple guy... P [#LetRottenTomatoesRotSquad, I, am, a, simple]
272 #LetRottenTomatoesRotSquad\nI am a simple guy... P [#LetRottenTomatoesRotSquad, I, am, a, simple]
116 A 'Triumph of the Will' for Nihilists\n'Joker... N [A, 'Triumph, of, the, Will']
18 A 'Triumph of the Will' for Nihilists\n'Joker... N [A, 'Triumph, of, the, Will']
214 A 'Triumph of the Will' for Nihilists\n'Joker... N [A, 'Triumph, of, the, Will']
In [179]:
sorted_v2 = v2.sort_values(by='Input.text')
sorted_v2[:6]
Out[179]:
HITId HITTypeId Title Description Keywords Reward CreationTime MaxAssignments RequesterAnnotation AssignmentDurationInSeconds ... RequesterFeedback WorkTimeInSeconds LifetimeApprovalRate Last30DaysApprovalRate Last7DaysApprovalRate Input.text Answer.sentiment.label Approve Reject for_matching
229 3AQN9REUTFGXCRWFMS3RJ4SIPSUYDG 3QUMZFVHE8V9K8DXS290QIIIHIS6R7 Sentiment analysis Sentiment analysis sentiment, text $0.02 Mon Nov 04 09:37:44 PST 2019 3 BatchId:3823577;OriginalHitTemplateId:928390909; 3600 ... NaN 61 0% (0/0) 0% (0/0) 0% (0/0) #LetRottenTomatoesRotSquad\nI am a simple guy... Positive NaN NaN [#LetRottenTomatoesRotSquad, I, am, a, simple]
228 3AQN9REUTFGXCRWFMS3RJ4SIPSUYDG 3QUMZFVHE8V9K8DXS290QIIIHIS6R7 Sentiment analysis Sentiment analysis sentiment, text $0.02 Mon Nov 04 09:37:44 PST 2019 3 BatchId:3823577;OriginalHitTemplateId:928390909; 3600 ... NaN 134 0% (0/0) 0% (0/0) 0% (0/0) #LetRottenTomatoesRotSquad\nI am a simple guy... Positive NaN NaN [#LetRottenTomatoesRotSquad, I, am, a, simple]
227 3AQN9REUTFGXCRWFMS3RJ4SIPSUYDG 3QUMZFVHE8V9K8DXS290QIIIHIS6R7 Sentiment analysis Sentiment analysis sentiment, text $0.02 Mon Nov 04 09:37:44 PST 2019 3 BatchId:3823577;OriginalHitTemplateId:928390909; 3600 ... NaN 15 0% (0/0) 0% (0/0) 0% (0/0) #LetRottenTomatoesRotSquad\nI am a simple guy... Positive NaN NaN [#LetRottenTomatoesRotSquad, I, am, a, simple]
53 3IVKZBIBJ09HSLP89IUSS3JF0ZRSH5 3QUMZFVHE8V9K8DXS290QIIIHIS6R7 Sentiment analysis Sentiment analysis sentiment, text $0.02 Mon Nov 04 09:37:41 PST 2019 3 BatchId:3823577;OriginalHitTemplateId:928390909; 3600 ... NaN 91 0% (0/0) 0% (0/0) 0% (0/0) A 'Triumph of the Will' for Nihilists\n'Joker... Neutral NaN NaN [A, 'Triumph, of, the, Will']
55 3IVKZBIBJ09HSLP89IUSS3JF0ZRSH5 3QUMZFVHE8V9K8DXS290QIIIHIS6R7 Sentiment analysis Sentiment analysis sentiment, text $0.02 Mon Nov 04 09:37:41 PST 2019 3 BatchId:3823577;OriginalHitTemplateId:928390909; 3600 ... NaN 24 0% (0/0) 0% (0/0) 0% (0/0) A 'Triumph of the Will' for Nihilists\n'Joker... Negative NaN NaN [A, 'Triumph, of, the, Will']
54 3IVKZBIBJ09HSLP89IUSS3JF0ZRSH5 3QUMZFVHE8V9K8DXS290QIIIHIS6R7 Sentiment analysis Sentiment analysis sentiment, text $0.02 Mon Nov 04 09:37:41 PST 2019 3 BatchId:3823577;OriginalHitTemplateId:928390909; 3600 ... NaN 66 0% (0/0) 0% (0/0) 0% (0/0) A 'Triumph of the Will' for Nihilists\n'Joker... Negative NaN NaN [A, 'Triumph, of, the, Will']

6 rows × 32 columns

In [192]:
all_df = sorted_v2.copy()
# all_df['PoN'] = sorted_labels['PoN'].tolist()
# THIS DIDN'T WORK BECAUSE I DIDN'T WAIT UNTIL ALL WERE DONE FROM AMT. RESEARCHER ERROR BUT OMG I HATE MYSELF
In [193]:
len(all_df)
Out[193]:
293
In [194]:
293/3
Out[194]:
97.66666666666667

Confirming that YEP. 293 isn't divisible by 3, meaning I didn't wait until the last turker finished. omg.

Reuploading now -- WITH BETTER CODE AND BETTER VARIABLE NAMES!

In [195]:
turker = pd.read_csv('HW5_amt_294.csv')
print(len(turker))
turker[:5]
294
Out[195]:
HITId HITTypeId Title Description Keywords Reward CreationTime MaxAssignments RequesterAnnotation AssignmentDurationInSeconds ... RejectionTime RequesterFeedback WorkTimeInSeconds LifetimeApprovalRate Last30DaysApprovalRate Last7DaysApprovalRate Input.text Answer.sentiment.label Approve Reject
0 338GLSUI43BXEPY2ES6SPI72KKESF7 3QUMZFVHE8V9K8DXS290QIIIHIS6R7 Sentiment analysis Sentiment analysis sentiment, text $0.02 Mon Nov 04 09:37:40 PST 2019 3 BatchId:3823577;OriginalHitTemplateId:928390909; 3600 ... NaN NaN 5 0% (0/0) 0% (0/0) 0% (0/0) Everyone praised an overrated movie.\nOverrat... Negative NaN NaN
1 338GLSUI43BXEPY2ES6SPI72KKESF7 3QUMZFVHE8V9K8DXS290QIIIHIS6R7 Sentiment analysis Sentiment analysis sentiment, text $0.02 Mon Nov 04 09:37:40 PST 2019 3 BatchId:3823577;OriginalHitTemplateId:928390909; 3600 ... NaN NaN 10 0% (0/0) 0% (0/0) 0% (0/0) Everyone praised an overrated movie.\nOverrat... Negative NaN NaN
2 338GLSUI43BXEPY2ES6SPI72KKESF7 3QUMZFVHE8V9K8DXS290QIIIHIS6R7 Sentiment analysis Sentiment analysis sentiment, text $0.02 Mon Nov 04 09:37:40 PST 2019 3 BatchId:3823577;OriginalHitTemplateId:928390909; 3600 ... NaN NaN 208 0% (0/0) 0% (0/0) 0% (0/0) Everyone praised an overrated movie.\nOverrat... Negative NaN NaN
3 37MQ8Z1JQEWA9HYZP3JANL1ES162YC 3QUMZFVHE8V9K8DXS290QIIIHIS6R7 Sentiment analysis Sentiment analysis sentiment, text $0.02 Mon Nov 04 09:37:40 PST 2019 3 BatchId:3823577;OriginalHitTemplateId:928390909; 3600 ... NaN NaN 658 0% (0/0) 0% (0/0) 0% (0/0) What idiotic FIlm\nI can say that Phoenix is ... Negative NaN NaN
4 37MQ8Z1JQEWA9HYZP3JANL1ES162YC 3QUMZFVHE8V9K8DXS290QIIIHIS6R7 Sentiment analysis Sentiment analysis sentiment, text $0.02 Mon Nov 04 09:37:40 PST 2019 3 BatchId:3823577;OriginalHitTemplateId:928390909; 3600 ... NaN NaN 1107 0% (0/0) 0% (0/0) 0% (0/0) What idiotic FIlm\nI can say that Phoenix is ... Negative NaN NaN

5 rows × 31 columns

In [197]:
# Getting labels...
labels = pd.read_csv('all_JK_extremes_labeled.csv')
# X3
labels = labels.append([labels] * 2, ignore_index=True)
print(len(labels))
labels[:5]
294
Out[197]:
0 PoN
0 Everyone praised an overrated movie.\nOverrat... N
1 What idiotic FIlm\nI can say that Phoenix is ... N
2 Terrible\nThe only thing good about this movi... N
3 Watch Taxi Driver instead\nThis is a poor att... N
4 I learned one thing.\nIt borrows a lot of ele... N

NOW, TO SORT!

In [198]:
sorted_labels = labels.sort_values(by=['0'])
sorted_turker = turker.sort_values(by=['Input.text'])
In [199]:
sorted_labels[:5]
Out[199]:
0 PoN
76 #LetRottenTomatoesRotSquad\nI am a simple guy... P
174 #LetRottenTomatoesRotSquad\nI am a simple guy... P
272 #LetRottenTomatoesRotSquad\nI am a simple guy... P
116 A 'Triumph of the Will' for Nihilists\n'Joker... N
18 A 'Triumph of the Will' for Nihilists\n'Joker... N
In [206]:
sorted_turker['Input.text'][:5]
Out[206]:
228     #LetRottenTomatoesRotSquad\nI am a simple guy...
229     #LetRottenTomatoesRotSquad\nI am a simple guy...
230     #LetRottenTomatoesRotSquad\nI am a simple guy...
56      A 'Triumph of the Will' for Nihilists\n'Joker...
55      A 'Triumph of the Will' for Nihilists\n'Joker...
Name: Input.text, dtype: object

OMG HOORAY HOORAY HOORAY!!

NOTE: FUN FACT!! I can type here and then hit the esc key to turn this cell into markdown!!

In [ ]: