Related
I am using open-source tesseract OCR to extract texts from the images. I need texts with proper space preserved and aligned for some information extraction tasks. I have used the tesseract .image_to_data() method. This method outputs the recognized texts along with its bounding box and confidence score.
After performing sorting I get all the texts on a string in the order they exist in the image but not formatted in the way that I want. One of my test images is
My code:
import cv2
import pytesseract
import argparse
import time
from pytesseract import Output
from utils.config import ENG_CONFIG
def check_confidence(df):
df = df[df['conf'] != -1]
return df
class OCR:
def __init__(self, conf, image):
self.conf = conf
self.image = image
def get_ocr_output(self):
result = pytesseract.image_to_data(self.image, config=self.conf, output_type=Output.DATAFRAME)
result = check_confidence(result)
lines, formatted_string = self.parse_texts(result)
return lines, formatted_string
def parse_texts(self, df):
img = self.image.copy()
parsed_info = []
start = time.time()
for row in df.itertuples(): # for index, row in df.iterrows()
loc = (row.left, row.top, row.width, row.height)
# draw box on the image
cv2.rectangle(img, (loc[0], loc[1]), (loc[0] + loc[2], loc[1] + loc[3]), (255, 255, 0), 2)
text = row.text
conf = row.conf
row_info = {'box': loc, 'text': text, 'conf': conf}
parsed_info.append(row_info)
end = time.time()
print("\n[INFO]: Total time to read the dataframe row by row is : {} seconds.".format(end - start))
print("\n[INFO]: Parsed Information before sorting boxes is: \n{}".format(parsed_info))
parsed_info = self.sort_box_vertically(parsed_info)
lines = self.get_lines_vertically(parsed_info)
lines = self.sort_box_horizontally(lines)
print("\n[INFO]: Parsed Information after sorting boxes horizontally-vertically is : \n{}".format(lines))
# formatted_strings = self.format_texts(lines)
formatted_strings = self.format_texts_by_reserving_spaces(lines)
print("\n[INFO] : Text for the image is : \n{}".format(formatted_strings))
cv2.imshow("text box", img)
cv2.waitKey(0)
return lines, formatted_strings
def sort_box_vertically(self, parsed_info):
"""
Method to sort the boxes vertically
:param parsed_info:
:return:
"""
for counter in range(len(parsed_info) - 1):
for num in range((len(parsed_info) - 1) - counter):
if self.get_box_center(parsed_info[num]['box'])[1] > self.get_box_center(parsed_info[num + 1]['box'])[
1]:
temp = parsed_info[num + 1]
parsed_info[num + 1] = parsed_info[num]
parsed_info[num] = temp
return parsed_info
def get_lines_vertically(self, parsed_info):
"""
Method to separate the lines vertically
:param parsed_info:
:return:
"""
lines = []
while len(parsed_info) != 0:
ref_box = parsed_info[0]['box']
line = [parsed_info[0]]
for i in range(1, len(parsed_info)):
if self.is_intersects(ref_box, parsed_info[i]['box']) or self.is_intersects(parsed_info[i]['box'],
ref_box):
line.append(parsed_info[i])
for i in range(len(line)):
parsed_info.remove(line[i])
lines.append(line)
return lines
def is_intersects(self, box1, box2, margin=0):
x_1, y_1, w_1, h_1 = box1
x_2, y_2, w_2, h_2 = box2
# check if box2 intersect with box1 by height
h1, k1 = self.get_box_center(box1)
h2, k2 = self.get_box_center(box2)
if int(k2) in range(int(y_1 + margin * h_1), int((y_1 + h_1 - h_1 * margin))) or int(k1) in range(
int(y_2 + margin * h_2), int((y_2 + h_2 - h_2 * margin))):
return True
return False
def get_box_center(self, box):
"""
Method to get the center of box (h,k)
:param box: box as tuple (x, y, w, h)
:return:
"""
x, y, w, h = box
x1 = x
y1 = y
x2 = x + w
y2 = y + h
# Find the center of the box
h, k = int((x1 + x2) / 2), int((y1 + y2) / 2)
return h, k
def format_texts(self, lines):
"""
Method to return the formatted texts from the image
:param lines:
:return:
"""
formatted_string = ""
for line in lines:
for word in line:
# print(word)
formatted_string += " " + word['text']
formatted_string += '\n'
return formatted_string
def format_texts_by_reserving_spaces(self, lines):
"""
An efficient Method to return the formatted texts from the image
:param lines:
:return:
"""
formatted_string = ""
for line in lines:
flag = 0
for word in line:
# print(word)
word_start = word['box'][0]
word_end = word['box'][0] + word['box'][2]
formatted_string += " " * (word_start - flag - 1) + word['text']
flag = word_end
formatted_string += '\n'
return formatted_string
def sort_box_horizontally(self, lines):
final_lines = []
for line in lines:
for counter in range(len(line) - 1):
for num in range((len(line) - 1) - counter):
# If x1 of first line is greater than second line
if self.get_box_center(line[num]['box'])[0] > self.get_box_center(line[num + 1]['box'])[0]:
temp = line[num + 1]
line[num + 1] = line[num]
line[num] = temp
final_lines.append(line)
return final_lines
def sort_box_horizontally_example(self, line_boxes):
"""
Method to sort the boxes horizontally
:param boxes: list of tuple of boxes eg:[((,),(,))]
:return:
"""
final_lines = []
for line in line_boxes:
for counter in range(len(line) - 1):
for num in range((len(line) - 1) - counter):
# If x1 of first line is greater than second line
if line[num][0][0] > line[num + 1][0][0]:
temp = line[num + 1]
line[num + 1] = line[num]
line[num] = temp
final_lines.append(line)
return final_lines
def sorting_example(self):
"""
Sorting array using bubble sort
:return:
"""
list_ = [3, 6, 8, 44, 77, 2, 44, 556, 66, 565, 34]
for i in range(len(list_) - 1):
for j in range((len(list_) - 1) - i):
if list_[j] > list_[j + 1]:
temp = list_[j]
list_[j] = list_[j + 1]
list_[j + 1] = temp
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--image',
default="./intelligent_information_extractor/images/img5.png",
help="Path to input image to be OCR'd")
args = parser.parse_args()
image = cv2.imread(args.image)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
ocr = OCR(ENG_CONFIG, image)
results = ocr.get_ocr_output()
The output it produces can be found here
While formatting texts which ocr outputs, I have converted a pixel to a single character. But it creates the text string where texts are separated by large whitespace.
So, How to decrease the whitespace to properly format the output texts by preserving all the spaces and alignment?
Style3 = TableStyle([('VALIGN',(0,0),(-1,-1),'TOP'),
('ALIGN',(0,0),(-1,-1),'RIGHT'),
('LEFTPADDING',(0,0),(-1,-1), 130),
('RIGHTPADDING',(0,0),(-1,-1), 0),
('TOPPADDING',(0,0),(-1,-1), 0),
])
I want response and categories label in starting but it show at the end of line, i want response and categories in from starting not end of line..
any special styling i need.
def getToolsTables(data,tname):
doc = SimpleDocTemplate("somefilename.pdf",pagesize=A2, topMargin=25, bottomMargin=0)
main_header = []
h_arr1 = []
h_arr1.append(tname)
main_header.append(h_arr1)
mainHeader = Table(main_header, colWidths='*')
finalTable = []
main_table_header_Style = TableStyle([
('BACKGROUND', (0, 0), (-1, 0), '#D3D3D3'),
('TEXTCOLOR',(0,0),(-1,-1),colors.black),
('ALIGN',(0,0),(-1,-1),'LEFT'),
('FONTSIZE', (0,0), (-1,-1), 12),
('FONTNAME', (0,0), (-1,-1),
'Courier-Bold'
),
('TOPPADDING',(0,0),(-1,-1), 5),
('BOTTOMPADDING',(0,0),(-1,-1), 7),
('LINEBELOW',(0,0),(-1,0),1,colors.black)
])
tools_table_header_Style = TableStyle([
('BACKGROUND', (0, 0), (-1, 0), 'lightblue'),
('TEXTCOLOR',(0,0),(-1,-1),colors.black),
('ALIGN',(0,0),(-1,-1),'LEFT'),
('FONTSIZE', (0,0), (-1,-1), 11),
('FONTNAME', (0,0), (-1,-1),
'Courier-Bold'),
])
tools_table_header_Style1 = TableStyle([
('BACKGROUND', (0, 0), (-1, 0), 'lightgreen'),
('TEXTCOLOR',(0,0),(-1,-1),colors.black),
('ALIGN',(0,0),(-1,-1),'CENTER'),
('FONTSIZE', (0,0), (-1,-1), 11),
('FONTNAME', (0,0), (-1,-1),
'Courier-Bold'),
])
Style2 = TableStyle([
('ALIGN',(0,0),(-1,-1),'LEFT'),
('LEFTPADDING',(0,0),(-1,-1), 0),
('RIGHTPADDING',(0,0),(-1,-1), 0),
('BOTTOMPADDING',(0,0),(-1,-1), -10),])
Style3 = TableStyle([('VALIGN',(0,0),(-1,-1),'TOP'),
('ALIGN',(0,0),(-1,-1),'RIGHT'),
('LEFTPADDING',(0,0),(-1,-1), 130),
('RIGHTPADDING',(0,0),(-1,-1), 0),
('TOPPADDING',(0,0),(-1,-1), 0),
])
mainHeader.setStyle(main_table_header_Style) # adding style to table main header
finalTable.append(mainHeader)
# Create Tools Array
tools_header = []
tools_body = []
# print(',,,,,,,,,,,,,,,,,,,,,,,,',data)
if type(data) == dict:
all_table = []
for key, value in data.items() :
temp = []
temp_table = []
temp.append(key)
tool_table_header = Table([temp],colWidths='*')
tool_table_header.setStyle(tools_table_header_Style)
temp_table.append(tool_table_header)
if key != 'Builtwith':
t_h = []
t_b = []
for k,v in value.items():
t_h.append(k)
t_b.append(v)
t_body = []
# import pdb; pdb.set_trace()
for index, item in enumerate(t_h):
if item != 'status':
arr1 = []
arr2 = []
if type(t_b[index]) is list:
temp_txt = ''
for txt in t_b[index]:
temp_txt += txt + ', '
arr1.append(item + ':')
text = t_b[index]
wraped_text = "\n".join(wrap(str(temp_txt[:-3]), 60)) # 60 is line width
arr1.append(wraped_text)
else:
arr1.append(item + ':')
text = t_b[index]
wraped_text = "\n".join(wrap(str(text), 60)) # 60 is line width
arr1.append(wraped_text)
arr2.append(arr1)
n_table =Table(arr2,[200,370])
t_body.append(n_table)
tool_header = Table([temp_table], colWidths='*')
tool_body = Table([[t_body]],[200,370])
finalTable.append(Table([[[tool_header,tool_body]]], colWidths='*'))
else:
for key,val in value.items():
temp1 = []
temp_table1 = []
temp1.append(key)
tool_table_header = Table([temp1],colWidths='*')
tool_table_header.setStyle(tools_table_header_Style1)
temp_table1.append(tool_table_header)
print('kkkkkkkk')
t_h = []
t_b = []
for k,v in val.items():
t_h.append(k)
t_b.append(v)
t_body = []
for index, item in enumerate(t_h):
if item != 'status':
arr1 = []
arr2 = []
if type(t_b[index]) is list:
temp_txt = ''
for txt in t_b[index]:
temp_txt += txt + ', '
arr1.append(item + ':')
text = t_b[index]
wraped_text = "\n".join(wrap(str(temp_txt[:-3]), 60)) # 60 is line width
arr1.append(wraped_text)
else:
arr1.append(item + ':')
text = t_b[index]
wraped_text = "\n".join(wrap(str(text), 80)) # 60 is line width
arr1.append(wraped_text)
arr2.append(arr1)
n_table =Table(arr2,[200,370])
t_body.append(n_table)
tool_header = Table([temp_table1], colWidths='*')
tool_header.setStyle(Style3)
tool_body = Table([[t_body]],[200,370])
table = Table([[[temp_table,tool_header,tool_body]]],colWidths='*')
finalTable.append(table)
else:
# finalTable.append(Table([['Tools Scan in progress...']], colWidths='*'))
finalTable.append(Table([[data]], colWidths='*'))
return finalTable
I want to change the name of the xls file that the user can download in Point of Sale module, Stock Pivot view.
on click of the download button in pivot view, Instead of "table.xls" I want it to be for example "03-17-2020.xls"
but I don't know how to change it
i tried looking for any source or example here or in the odoo forum but i can't see any
Try To this code in Your controller/ section
from collections import deque
import json
from odoo import http
from odoo.http import request
from odoo.tools import ustr
from odoo.tools.misc import xlwt
from datetime import date
from odoo.addons.web.controllers.pivot import TableExporter # Import the class
class CustomTableExporter(TableExporter):# Inherit in your custom class
#http.route('/web/pivot/export_xls', type='http', auth="user")
def export_xls(self, data, token):
jdata = json.loads(data)
nbr_measures = jdata['nbr_measures']
workbook = xlwt.Workbook()
worksheet = workbook.add_sheet(jdata['title'])
header_bold = xlwt.easyxf("font: bold on; pattern: pattern solid, fore_colour gray25;")
header_plain = xlwt.easyxf("pattern: pattern solid, fore_colour gray25;")
bold = xlwt.easyxf("font: bold on;")
# Step 1: writing headers
headers = jdata['headers']
# x,y: current coordinates
# carry: queue containing cell information when a cell has a >= 2 height
# and the drawing code needs to add empty cells below
x, y, carry = 1, 0, deque()
for i, header_row in enumerate(headers):
worksheet.write(i, 0, '', header_plain)
for header in header_row:
while (carry and carry[0]['x'] == x):
cell = carry.popleft()
for i in range(nbr_measures):
worksheet.write(y, x + i, '', header_plain)
if cell['height'] > 1:
carry.append({'x': x, 'height': cell['height'] - 1})
x = x + nbr_measures
style = header_plain if 'expanded' in header else header_bold
for i in range(header['width']):
worksheet.write(y, x + i, header['title'] if i == 0 else '', style)
if header['height'] > 1:
carry.append({'x': x, 'height': header['height'] - 1})
x = x + header['width']
while (carry and carry[0]['x'] == x):
cell = carry.popleft()
for i in range(nbr_measures):
worksheet.write(y, x + i, '', header_plain)
if cell['height'] > 1:
carry.append({'x': x, 'height': cell['height'] - 1})
x = x + nbr_measures
x, y = 1, y + 1
# Step 2: measure row
if nbr_measures > 1:
worksheet.write(y, 0, '', header_plain)
for measure in jdata['measure_row']:
style = header_bold if measure['is_bold'] else header_plain
worksheet.write(y, x, measure['measure'], style)
x = x + 1
y = y + 1
# Step 3: writing data
x = 0
for row in jdata['rows']:
worksheet.write(y, x, row['indent'] * ' ' + ustr(row['title']), header_plain)
for cell in row['values']:
x = x + 1
if cell.get('is_bold', False):
worksheet.write(y, x, cell['value'], bold)
else:
worksheet.write(y, x, cell['value'])
x, y = 0, y + 1
today = date.today()
a = str(today) + '.xls'
response = request.make_response(None,
headers=[('Content-Type', 'application/vnd.ms-excel'),
('Content-Disposition', 'attachment; filename=%s' % a)],
cookies={'fileToken': token})
workbook.save(response.stream)
return response
This will print Today date name as excel - 2020-03-18.xls
I am trying to create a class Tile and use it in another method. However, when I run the code (below), the error is raised: AttributeError: type object 'Tile' has no attribute 'row'.
As I pop the class from the queue (Python list) and try to print it, it prints the value of the row (which is 0) but then gives the AttributeError.
Why is it saying that the attribute row does not exist?
"""
Shortest distance between two cells in a matrix or grid
"""
class Tile:
def __init__(self, row, col, dist):
self.row = row
self.col = col
self.dist = dist
def min_path(rows, cols, lot):
start_node = Tile(0, 0, 0)
q = []
q.append(start_node)
visited = [[False]*cols for i in range(rows)]
for i in range(rows):
for j in range(cols):
if lot[i][j] == 0:
visited[i][j] = True
while q:
new_tile = q.pop(0)
print(new_tile.row)
if lot[new_tile.row][new_tile.col] == 9:
return new_tile.dist
if new_tile.row - 1 >= 0 and visited[new_tile.row - 1][new_tile.col] == False:
Tile(new_tile.row - 1, new_tile.col, new_tile.dist + 1)
q.append(Tile)
visited[new_tile.row - 1][new_tile.col] = True
if new_tile.row + 1 < rows and visited[new_tile.row + 1][new_tile.col] == False:
Tile(new_tile.row + 1, new_tile.col, new_tile.dist + 1)
q.append(Tile)
visited[new_tile.row + 1][new_tile.col] = True
if new_tile.col - 1 >= 0 and visited[new_tile.row][new_tile.col - 1] == False:
Tile(new_tile.row, new_tile.col - 1, new_tile.dist + 1)
q.append(Tile)
visited[new_tile.row][new_tile.col - 1] = True
if new_tile.col + 1 < cols and visited[new_tile.row][new_tile.col + 1] == False:
Tile(new_tile.row, new_tile.col + 1, new_tile.dist + 1)
q.append(Tile)
visited[new_tile.row][new_tile.col + 1] = True
return -1
if __name__ == "__main__":
lot = [
[1, 0, 0, 0],
[1, 0, 1, 0],
[1, 1, 0, 0],
[0, 1, 9, 0],
]
result = min_path(4, 4, lot)
print(result)
When I run this file, this is the output:
0
Traceback (most recent call last):
File "code.py", line 568, in <module>
result = min_path(4, 4, lot)
File "code.py", line 533, in min_path
print(new_tile.row)
AttributeError: type object 'Tile' has no attribute 'row'
Seems to be because of these lines: q.append(Tile). You are appending a reference to the class itself instead of an instance of it. Instead try something like
tile = Tile(new_tile.row - 1, new_tile.col, new_tile.dist + 1)
q.append(tile)
This was working and now has stopped and is giving me an error I can't see what's wrong with it?
def grade(R):
x = str(R)
if 'Practitioner' in x:
y = x.replace('Practitioner', ' ')
elif 'P' in x:
y = x.replace('P', ' ')
elif 'p' in x:
y = x.replace('p', ' ')
elif 'Graduate' in x:
y = x.replace('Graduate', ' ')
elif 'G' in x:
y =x.replace('G', ' ')
elif 'g' in x:
y = x.replace('g', ' ')
y = int(y)
g = inf.number_to_words(y)
return (g)
Full Script
import datetime
import os
from random import choice
from string import digits
import subprocess
import inflect
import pandas as pd
import reportlab
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen import canvas
# import xlrd
from reportlab.lib.units import mm
# set inflect
inf = inflect.engine()
# set fonts
folder = os.path.dirname(reportlab.__file__) + os.sep + 'fonts'
ttfFile_b = os.path.join(folder, 'VeraBd.ttf')
ttfFile_r = os.path.join(folder, 'Vera.ttf')
pdfmetrics.registerFont(TTFont("VeraBd", ttfFile_b))
pdfmetrics.registerFont(TTFont("Vera", ttfFile_r))
# Set date usage stuff
w = datetime.datetime.now()
d = datetime.date.today()
m = d.month
y = d.year + 1
p = str(w.hour) + '-' + str(w.minute) + '_' + str(w.second)
end_date = str(m) + '/' + str(y)
def grade(R):
x = str(R)
if 'Practitioner' in x:
y = x.replace('Practitioner', ' ')
elif 'P' in x:
y = x.replace('P', ' ')
elif 'p' in x:
y = x.replace('p', ' ')
elif 'Graduate' in x:
y = x.replace('Graduate', ' ')
elif 'G' in x:
y =x.replace('G', ' ')
elif 'g' in x:
y = x.replace('g', ' ')
y = int(y)
g = inf.number_to_words(y)
return (g)
def level(R):
x = str(R)
y = x.replace('Practitioner', ' ')
int(y)
g = inf.number_to_words(y)
return (g)
# Routine to get location
def location(L):
x = str(L)
if 'London' in x:
l = str("London")
elif 'Stratford' in x:
l = str("Stratford Upon Avon")
elif 'Bristol' in x:
l = str("Bristol")
elif 'Penrith' in x:
l = str("Penrith")
else:
l = str("United Kingdom")
return (l)
# Get date
def when(D):
dt = D.strftime('%d %B %Y')
d = str(dt)
return (d)
# get random diploma number
def dip():
x = ''.join(choice(digits) for i in range(6))
k = str(x)
return (k)
def p_certs(df):
# set PDF file name and canvas size
# file_location = 'C:\Users\Suely\Desktop\Ouput_PDF\'
# Set date usage stuff
w = datetime.datetime.now()
d = datetime.date.today()
m = d.month
y = d.year + 1
p = str(w.hour) + '-' + str(w.minute) + '_' + str(w.second)
# end_date = str(m) + '/' + str(y)
file_name = 'CERTIFICATES_' + str(d) + '_' + str(p) + '.pdf'
c = canvas.Canvas(file_name, pagesize=(210 * mm, 297 * mm))
# 1mm = 0.35277777 pt
# draw each page
for index, row in df.iterrows():
# D = str(row['Date'])
# R = row['Grading Level (National Grading)']
# L = row['Select Grading Event']
# g = location(L)
# A = row['Grading Committee']
# I = row['Instructor']
g = row['Location']
fn = str.strip(row['First Name'])
ln = str.strip(row['Last Name'])
f = row['Grade']
# r = row['Grade']
r = grade(f)
# d = str('11 August 2018')
# d = when(D)
d = str(row['Date'])
N = fn + ' ' + ln
# N = row['First Name'] + ' ' + row['Last Name']
# N = row['First Name'] + row['Last Name']
k = dip()
#k2 = str('KMG-UK -') + str(k)
k2 = row['Diploma Number']
# Draw Name
c.setFont('VeraBd', 24, leading=None)
c.drawCentredString(297.63786, 160 * mm, str.title(N))
# Draw Grade
c.setFont('VeraBd', 18, leading=None)
c.drawCentredString(110 * mm, 130 * mm, str.upper(r))
# Draw Place
c.setFont('VeraBd', 14, leading=None)
# c.drawCentredString(297.63786, 261.8581643, str.title(g))
c.drawCentredString(105 * mm, 91 * mm, str.upper(g))
# Draw Date
c.setFont('VeraBd', 14, leading=None)
# c.drawCentredString(297.63786, 236.3463527, str.title(d))
c.drawCentredString(105 * mm, 81 * mm, str(d))
# Draw Diploma number
c.setFont('VeraBd', 11, leading=None)
c.drawCentredString(105 * mm, 71 * mm, str.upper(k2))
c.showPage()
# Draw Administration & Instructor
# c.setFont('VeraBd', 12, leading=None)
# c.drawCentredString(60*mm, 25*mm, str.upper(I))
# c.setFont('VeraBd', 12, leading=None)
# c.drawCentredString(105*mm, 25*mm, str.upper(A))
c.save()
subprocess.Popen([file_name], shell=True)
# set data file
data_location = '007. P1_P2 Data Sheet.csv'
file_name2 = '007. P1_P2 Data Sheet.xlsx'
# read dataframe
df = pd.read_csv(data_location, encoding='latin1', na_values=['nan'], keep_default_na=False)
# df = pd.read_excel(file_name2, 'Sheet1', index_col=None, na_values=['NA'])
p_certs(df)
The Error
C:\Users\James\AppData\Local\Programs\Python\Python37\python.exe "D:/Dropbox/Dropbox/00000001 Licence Print/P certs/002 P1 Certificates/Certificatea.py"
Traceback (most recent call last):
File "D:/Dropbox/Dropbox/00000001 Licence Print/P certs/002 P1 Certificates/Certificatea.py", line 179, in
p_certs(df)
File "D:/Dropbox/Dropbox/00000001 Licence Print/P certs/002 P1 Certificates/Certificatea.py", line 127, in p_certs
r = grade(f)
File "D:/Dropbox/Dropbox/00000001 Licence Print/P certs/002 P1 Certificates/Certificatea.py", line 50, in grade
y = int(y)
UnboundLocalError: local variable 'y' referenced before assignment
Process finished with exit code 1
Your local variable y would not be initialized before its usage in the statement y = int(y) if none of the if and elif conditions before it are met.
You can assign to y a default value in an else clause instead:
def grade(R):
x = str(R)
if 'Practitioner' in x:
y = x.replace('Practitioner', ' ')
elif 'P' in x:
y = x.replace('P', ' ')
elif 'p' in x:
y = x.replace('p', ' ')
elif 'Graduate' in x:
y = x.replace('Graduate', ' ')
elif 'G' in x:
y =x.replace('G', ' ')
elif 'g' in x:
y = x.replace('g', ' ')
else:
y = '0'
y = int(y)
g = inf.number_to_words(y)
return (g)
Or you can try fixing your input data to ensure that the argument R would always result in satisfying one of the conditions in the if and elif clauses.