IndexError: list index out of range with api - python

all_currencies = currency_api('latest', 'currencies') # {'eur': 'Euro', 'usd': 'United States dollar', ...}
all_currencies.pop('brl')
qtd_moedas = len(all_currencies)
texto = f'{qtd_moedas} Moedas encontradas\n\n'
moedas_importantes = ['usd', 'eur', 'gbp', 'chf', 'jpy', 'rub', 'aud', 'cad', 'ars']
while len(moedas_importantes) != 0:
for codigo, moeda in all_currencies.items():
if codigo == moedas_importantes[0]:
cotacao, data = currency_api('latest', f'currencies/{codigo}/brl')['brl'], currency_api('latest', f'currencies/{codigo}/brl')['date']
texto += f'{moeda} ({codigo.upper()}) = R$ {cotacao} [{data}]\n'
moedas_importantes.remove(codigo)
if len(moedas_importantes) == 0: break # WITHOUT THIS LINE, GIVES ERROR
Why am I getting this error? the list actually runs out of elements, but the code only works with the if

You have a nested loop. The while loop is entered and then execution immediately starts in the for loop. Execution remains in the for loop for all elements in all_currencies.items(). Each time codigo is found at the beginning of moedas_importantes, that element is removed. Eventually you remove all elements from moedas_importantes, but you are still in the for loop and check if codigo == moedas_importantes[0]. At this point moedas_importantes is empty so you get an index error.
I think the below code will work without the nested loops. Note, this assumes all elements in moedas_importantes are also keys in all_currencies.
all_currencies = currency_api('latest', 'currencies') # {'eur': 'Euro', 'usd': 'United States dollar', ...}
all_currencies.pop('brl')
qtd_moedas = len(all_currencies)
texto = f'{qtd_moedas} Moedas encontradas\n\n'
moedas_importantes = ['usd', 'eur', 'gbp', 'chf', 'jpy', 'rub', 'aud', 'cad', 'ars']
while len(moedas_importantes) != 0:
codigo = moedas_importantes[0]
moeda = all_currencies[codigo]
cotacao, data = currency_api('latest', f'currencies/{codigo}/brl')['brl'], currency_api('latest', f'currencies/{codigo}/brl')['date']
texto += f'{moeda} ({codigo.upper()}) = R$ {cotacao} [{data}]\n'
moedas_importantes.remove(codigo)

Related

Pass elements of a list in a function

I have a function that is able to create triples and relationships from text. However, when I create a list of a column that contains text and pass it through the function, it only processes the first row, or item of the list. Therefore, I am wondering how the whole list can be processed within this function. Maybe a for loop would work?
The following line contains the list
rez_dictionary = {'Decent Little Reader, Poor Tablet',
'Ok For What It Is',
'Too Heavy and Poor weld quality,',
'difficult mount',
'just got it installed'}
from transformers import pipeline
triplet_extractor = pipeline('text2text-generation', model='Babelscape/rebel-large', tokenizer='Babelscape/rebel-large')
# We need to use the tokenizer manually since we need special tokens.
extracted_text = triplet_extractor.tokenizer.batch_decode([triplet_extractor(rez_dictionary, return_tensors=True, return_text=False)[0]["generated_token_ids"]])
print(extracted_text[0])
If anyone has a suggestion, I am looking forward for it.
Would it also be possible to get the output adjusted to the following format:
# Function to parse the generated text and extract the triplets
def extract_triplets(text):
triplets = []
relation, subject, relation, object_ = '', '', '', ''
text = text.strip()
current = 'x'
for token in text.replace("<s>", "").replace("<pad>", "").replace("</s>", "").split():
if token == "<triplet>":
current = 't'
if relation != '':
triplets.append({'head': subject.strip(), 'type': relation.strip(),'tail': object_.strip()})
relation = ''
subject = ''
elif token == "<subj>":
current = 's'
if relation != '':
triplets.append({'head': subject.strip(), 'type': relation.strip(),'tail': object_.strip()})
object_ = ''
elif token == "<obj>":
current = 'o'
relation = ''
else:
if current == 't':
subject += ' ' + token
elif current == 's':
object_ += ' ' + token
elif current == 'o':
relation += ' ' + token
if subject != '' and relation != '' and object_ != '':
triplets.append({'head': subject.strip(), 'type': relation.strip(),'tail': object_.strip()})
return triplets
extracted_triplets = extract_triplets(extracted_text[0])
print(extracted_triplets)
You are removing the other entries of rez_dictionary inside the batch_decode:
triplet_extractor(rez_dictionary, return_tensors=True, return_text=False)[0]["generated_token_ids"]
Use a list comprehension instead:
from transformers import pipeline
rez = ['Decent Little Reader, Poor Tablet',
'Ok For What It Is',
'Too Heavy and Poor weld quality,',
'difficult mount',
'just got it installed']
triplet_extractor = pipeline('text2text-generation', model='Babelscape/rebel-large', tokenizer='Babelscape/rebel-large')
model_output = triplet_extractor(rez, return_tensors=True, return_text=False)
extracted_text = triplet_extractor.tokenizer.batch_decode([x["generated_token_ids"] for x in model_output])
print("\n".join(extracted_text))
Output:
<s><triplet> Decent Little Reader <subj> Poor Tablet <obj> different from <triplet> Poor Tablet <subj> Decent Little Reader <obj> different from</s>
<s><triplet> Ok For What It Is <subj> film <obj> instance of</s>
<s><triplet> Too Heavy and Poor <subj> weld quality <obj> subclass of</s>
<s><triplet> difficult mount <subj> mount <obj> subclass of</s>
<s><triplet> 2008 Summer Olympics <subj> 2008 <obj> point in time</s>
Regarding the extension of the OP's question, OP wanted to know how to run the function extract_triplets. OP can simply do that via a for-loop:
for text in extracted_text:
print(extract_triplets(text))
Output:
[{'head': 'Decent Little Reader', 'type': 'different from', 'tail': 'Poor Tablet'}, {'head': 'Poor Tablet', 'type': 'different from', 'tail': 'Decent Little Reader'}]
[{'head': 'Ok For What It Is', 'type': 'instance of', 'tail': 'film'}]
[{'head': 'Too Heavy and Poor', 'type': 'subclass of', 'tail': 'weld quality'}]
[{'head': 'difficult mount', 'type': 'subclass of', 'tail': 'mount'}]
[{'head': '2008 Summer Olympics', 'type': 'point in time', 'tail': '2008'}]

Replace element of list with string from another list

So I wrote this but it doesn't accomplish what I want to do. Basically, I want to replace the number in the second index with whatever the word is at that index in the content_list list.
content_list= ['abstract', 'bow', 'button', 'chiffon', 'collar', 'cotton', 'crepe', 'crochet', 'crop', 'embroidered', 'floral', 'floralprint', 'knit', 'lace', 'longsleeve', 'peasant', 'pink', 'pintuck', 'plaid', 'pleated', 'polkadot', 'printed', 'red', 'ruffle', 'sheer', 'shirt', 'sleeve', 'sleeveless', 'split', 'striped', 'summer', 'trim', 'tunic', 'v-neck', 'woven', '']
max=[['Img/img/Sheer_Pleated-Front_Blouse/img_00000001.jpg', '24'],['Img/img/Sheer_Pleated-Front_Blouse/img_00000001.jpg', '19,15,24']]
for l in max:
e=l[1]
f=e.split(",")
for s in f:
intt=int(s)
rep=content_list[intt]
#print(rep)
e.replace(s,rep)
#print(z)
print(max)
This is the output that i get:
[['Img/img/Sheer_Pleated-Front_Blouse/img_00000001.jpg', '24'], ['Img/img/Sheer_Pleated-Front_Blouse/img_00000001.jpg', '19,15,24']]
But this is what i want:
[['Img/img/Sheer_Pleated-Front_Blouse/img_00000001.jpg', 'sheer'], ['Img/img/Sheer_Pleated-Front_Blouse/img_00000001.jpg', 'pleated,peasant,sheer']]
First of all, max is a built-in function I would highly recommend you to check how to name variables for the future, It may cause some big problems for you :).
You can brute-force your way out here also something like this:
arr = [
['Img/img/Sheer_Pleated-Front_Blouse/img_00000001.jpg', '24'],
['Img/img/Sheer_Pleated-Front_Blouse/img_00000001.jpg', '19,15,24'],
]
for inner in arr:
indexes=inner[1]
inner[1] = ""
for number in indexes.split(","):
inner[1] += content_list[int(number)]
print(inner)
I would do something like this, I think must be better options but it works... so it's better than nothing
content_list = ['abstract', 'bow', 'button', 'chiffon',
'collar', 'cotton', 'crepe', 'crochet',
'crop', 'embroidered', 'floral', 'floralprint',
'knit', 'lace', 'longsleeve', 'peasant', 'pink',
'pintuck', 'plaid', 'pleated', 'polkadot', 'printed',
'red', 'ruffle', 'sheer', 'shirt', 'sleeve', 'sleeveless',
'split', 'striped', 'summer', 'trim', 'tunic',
'v-neck', 'woven', '']
target_array = [['Img/img/Sheer_Pleated-Front_Blouse/img_00000001.jpg', '24'],
['Img/img/Sheer_Pleated-Front_Blouse/img_00000001.jpg', '19,15,24']]
for id_target, el in enumerate(target_array):
for num in el[1].split(','):
target_array[id_target][1] = target_array[id_target][1].replace(num,
content_list[int(num)])
Here is the solution:
import numpy as np
c= ['abstract', 'bow', 'button', 'chiffon', 'collar', 'cotton', 'crepe', 'crochet', 'crop', 'embroidered', 'floral', 'floralprint', 'knit', 'lace', 'longsleeve', 'peasant', 'pink', 'pintuck', 'plaid', 'pleated', 'polkadot', 'printed', 'red', 'ruffle', 'sheer', 'shirt', 'sleeve', 'sleeveless', 'split', 'striped', 'summer', 'trim', 'tunic', 'v-neck', 'woven', '']
m=[['Img/img/Sheer_Pleated-Front_Blouse/img_00000001.jpg', '24'],['Img/img/Sheer_Pleated-Front_Blouse/img_00000001.jpg', '19,15,24']]
n = np.copy(m)
for i in range(np.size(m,1)):
for j in range(np.size(m[i][1].split(','))):
idx = m[i][1].split(',')[j]
if (j==0):
n[i][1] = c[int(idx)]
else:
n[i][1] += ',' + c[int(idx)]
print(n)
The output:
[['Img/img/Sheer_Pleated-Front_Blouse/img_00000001.jpg' 'sheer']
['Img/img/Sheer_Pleated-Front_Blouse/img_00000001.jpg'
'pleated,peasant,sheer']]

Exclude positionAmt values of dict [jsonArray] object with python

I get the following json object with python. I want to exclude the following object whose positionAmt value is greater than 0. How can I do that ?
If the value of positionAmt is zero and greater then delete the row it is on.
def webhook(request):
webhook_received_json = json.loads(request.body)
while True:
get_active_position()
def get_active_position():
print("get_active position")
sleep(3)
futures_api_key = "asd"
futures_secret_key = "fdg"
client = Client(futures_api_key, futures_secret_key)
data = client.futures_position_information()
# data = list
for key, value in data.items():
if "positionAmt" >= "0.0000":
del data[key]
break
return get_active_position
[
{'symbol': 'BCHUSDT', 'positionAmt': '0.00000', 'entryPrice': '262.39000'},
,{'symbol': 'BCHUSDT', 'positionAmt': '-0.001', 'entryPrice': '262.39000'},
{'symbol': 'ETHUSDT', 'positionAmt': '-0.001', 'entryPrice': '386.60000'}]
The value is a string. you need it to convert to float or decimal.Decimal in order to compare properly. Also you iterate over a list.
def get_active_position():
print("get_active position")
sleep(3)
futures_api_key = "asd"
futures_secret_key = "fdg"
client = Client(futures_api_key, futures_secret_key)
data = client.futures_position_information()
return [item for item in data if float(item.get('positionAmt', '0')) < 0]
Note, the code is not tested
EDIT: I edit the code so that it will exclude 0

Is there a faster way with do this?

So I'm doing a python project and I need to organize a list of values by dictionary. I would like to know if there's a faster way than just doing what I'm doing.
This is what I've done, is there a more efficient and easier way to do this?
def catogorize_by_mortality(hurricanes):
damage_scale = {0: 0, 1: 100, 2: 500, 3: 1000, 4: 1e4}
hurricane_mortality_dict = {0:[], 1:[], 2:[], 3:[], 4:[], 5:[]}
for hurricane in hurricanes:
current_hurricane = hurricanes[hurricane]
death_count = current_hurricane['Deaths']
if death_count > damage_scale[0] and death_count < damage_scale[1]:
hurricane_mortality_dict[0] += hurricane
elif death_count > damage_scale[1] and death_count < damage_scale[2]:
hurricane_mortality_dict[1] += hurricane
elif death_count > damage_scale[2] and death_count < damage_scale[3]:
hurricane_mortality_dict[2] += hurricane
elif death_count > damage_scale[3] and death_count < damage_scale[4]:
hurricane_mortality_dict[3] += hurricane
elif death_count >= damage_scale[4]:
hurricane_mortality_dict[4] += hurricane
else:
hurricane_mortality_dict[5] += hurricane
return hurricane_mortality_dict
# example of the hurricanes dictionary when printed
{'Cuba I': {'Name': 'Cuba I', 'Month': 'October', 'Year': 1924, 'Max Sustained Wind': 165, 'Areas Affected': ['Central America', 'Mexico', 'Cuba', 'Florida', 'The Bahamas'], 'Deaths': 90}
# this is what it returns
deaths.')
{0: ['C', 'u', 'b', 'a'
What's supposed to happen is that it will return the hurricane's names categorized but instead it splits them up into characters what's happening?
hurricane_mortality_dict[i] is defined as a list, near the top of the function:
hurricane_mortality_dict = {0:[], 1:[], 2:[], 3:[], 4:[], 5:[]}
So in your conditional, when you do hurricane_mortality_dict[i] += hurricane, you're trying to add a string and a list, which treats the string as a list of characters - hence your output.
All you need to do is change each:
hurricane_mortality_dict[i] += hurricane
to:
hurricane_mortality_dict[i].append(hurricane)
For your example input this then results in:
{0: ['Cuba I'], 1: [], 2: [], 3: [], 4: [], 5: []}

How to accelerate the following function in Python

I have a complex function which takes forever to run on large pandas dataframe and I do not find ways to accelerate it. Do you guys have any tip?
I have used numba, but this is clearly not enough. I have also tried to used index reference to exploit pandas capacity to the maximum but, I am sure there are other ways I have not implemented.
What this function does, is basically takes a dataframe with random time spaced events and normalize it into second spaced events. There are three different types of events (TRADE, BEST_BID, BEST_ASK), so for each second I should have three lines (one of each event). If not event of a specific type happened during that second, we reuse previous value.
Thank you for your help!
#numba.jit
def convertTicksToSeconds(dataFrame_df):
idxs = dataFrame_df['data_all'][dataFrame_df['data_all']['time_change']].index.tolist()
previous_idx = 0
progress_i = 0
#Creation of the df to holfd the normalized data
normalized_Data = pandas.DataFrame( columns=['timestamp', 'B.A.T', 'price', 'volume', 'asset'])
BAT_type =['TRADE','BEST_BID','BEST_ASK']
tmp_time = dataFrame_df['data_all']['timestamp'][0]
data_TRADE = {'timestamp': tmp_time, 'B.A.T': 'TRADE', 'price': 0, 'volume': 0, 'asset': dataFrame_df['data_all']['asset'][0]}
data_BID = {'timestamp': tmp_time, 'B.A.T': 'BEST_BID', 'price': 0, 'volume': 0, 'asset': dataFrame_df['data_all']['asset'][0]}
data_ASK = {'timestamp': tmp_time, 'B.A.T': 'BEST_ASK', 'price': 0, 'volume': 0, 'asset': dataFrame_df['data_all']['asset'][0]}
for BAT in BAT_type:
for idx in idxs:
if dataFrame_df['data_all'][previous_idx:idx-1][dataFrame_df['data_all']['B.A.T'] == BAT].empty == False:
timestamp = dataFrame_df['data_all']['timestamp'][idx]
price = dataFrame_df['data_all']['price'][previous_idx:idx-1][dataFrame_df['data_all']['B.A.T'] == BAT]
volume = dataFrame_df['data_all']['volume'][previous_idx:idx-1][dataFrame_df['data_all']['B.A.T'] == BAT]
total_volume = volume.sum()
weighted_price = price * volume
weighted_price = weighted_price.sum() / total_volume
volume = volume.mean()
asset = dataFrame_df['data_all']['asset'][idx]
if BAT == 'TRADE':
data_TRADE = {'timestamp': timestamp, 'B.A.T': BAT, 'price': weighted_price, 'volume': volume, 'asset': asset}
elif BAT == 'BEST_BID':
data_BID = {'timestamp': timestamp, 'B.A.T': BAT, 'price': weighted_price, 'volume': volume, 'asset': asset}
elif BAT == 'BEST_ASK':
data_ASK = {'timestamp': timestamp, 'B.A.T': BAT, 'price': weighted_price, 'volume': volume, 'asset': asset}
print data_TRADE
print data_BID
print data_ASK
normalized_Data.append(data_TRADE, ignore_index=True)
normalized_Data.append(data_BID, ignore_index=True)
normalized_Data.append(data_ASK, ignore_index=True)
previous_idx = idx
progress_i += 1
tmp = (progress_i / len(idxs))*100
print ('Progress : ' + str(tmp) + ' %')
return normalized_Data

Categories

Resources