Related
I am using PulP to solve a linear programming problem. I am having the following error in the objective function:
TypeError: list indices must be integers or slices, not str
My objective function is
prob += lpSum([routes_vars][man][pa]*costs_distance[man][pa] for (man,pa) in routes)
according to the error message, I think my problem is the costs_distance dictionary that has string values
costs_distance = {'201': {'10267': '167724.1407', '10272': '151859.5908', '10275': '150131.7254', '10277': '153266.1819', '10279': '147949.5275', '10281': '145429.9767', '10283': '144757.2507', '10286': '166474.849', '10288': '152733.6419'}, '2595': {'10267': '186216.5193', '10272': '170351.9694', '10275': '168624.1039', '10277': '171758.5604', '10279': '166441.906', '10281': '163922.3553', '10283': '163249.6293', '10286': '186363.4807', '10288': '171226.0204'},
How can I convert only the dictionary string values ('167724.1407', '151859.5908', '150131.7254'... ) into int values?
Your issue has nothing to do with the costs_distance dictionary (otherwise the error message wouldn't mention a list). It's this part:
[routes_vars][man][pa]
I'm not sure what you expect this to return, but it first constructs a list with a single element (routes_vars) then tries to slice it using [man], which doesn't make any sense.
If sure you meant converting dictionary values to float and not int
list1 = costs_distance['201'].values()
list2 = list(map(float, list1))
I'm working with a numpy array called "C_ClfGtLabels" in which 374 artist/creator names are stored. I want to append a 375th artist class with a string "other artists". I thought I could just do that as follows:
C_ClfGtLabels.append('other artists')
However, this results in the following error:
AttributeError: 'numpy.ndarray' object has no attribute 'append'
I saw found this problem a few times on stackoverflow, to which the answer in one case was to use concatenate instead of append. When I tried that I got the following error:
TypeError: don't know how to convert scalar number to int
It seems to be a problem that the datatype does not match the datatype that I, trying to append/concatenate, which would be of type string. However, I don't know what I should do to make them match. The data inside the Clabels array is as follows:
[u"admiral, jan l'" u'aldegrever, heinrich' u'allard, abraham'
u'allard, carel' u'almeloveen, jan van' u'altdorfer, albrecht'
u'andriessen, jurriaan' u'anthonisz., cornelis' u'asser, eduard isaac' ..]
Any advice on how I can setup the "other artists" string so that I can append it to C_ClfGtLabels?
A quick workaround is to convert your C_ClfGtLabels into a list first, append, and convert it back into an ndarray
lst = list(C_ClfGtLabels)
lst.append('other artists')
C_ClfGtLabels = np.asarray(lst)
I have a multidimensionnal dict, I need to return a specific value.
ConsomRatio={"DAP_Local":[],"MAP11_52":[]}
ConsomRatio["DAP_Local"].append({"Ammonia":"0.229", "Amine":"0.0007"})
ConsomRatio["MAP11_52"].append({"Ammonia":"0.138", "Fuel":"0.003"})
print(ConsomRatio["DAP_Local"])
The result of the print is:
[{'Ammonia': '0.229', 'Amine': '0.0007'}]
My question is : Is there a way to return the value of "Ammonia" only, in "DAP_Local" ?
Thank you!
You can get to it like this. You're appending your dict to a list, so you must select the correct index in the list where the dict is located. In this case the first element in the list or index 0.
ConsomRatio["DAP_Local"][0]["Ammonia"]
By the way, depending on what you are trying to achieve you might wanna take a look at the other answers for different implementations of multi-dimensional dicts.
The other answers are of course correct, but have you considered using a "dict of dicts"? i.e.:
ConsomRatio={"DAP_Local":{},"MAP11_52":{}}
ConsomRatio["DAP_Local"].update({"Ammonia":"0.229", "Amine":"0.0007"})
ConsomRatio["MAP11_52"].update({"Ammonia":"0.138", "Fuel":"0.003"})
print ConsomRatio["DAP_Local"]["Ammonia"]
0.229
since print(ConsomRatio["DAP_Local"]) returns an array of length 1, you need to select the index 0, then key off the 'Ammonia' value as above.
if print(ConsomRatio["DAP_Local"]) returned a dict, then no need to have the [0] and print(ConsomRatio["DAP_Local"]['Amomonia']) would have worked
Why are you putting lists in your dict, anyhow? You can just use dicts inside your main dict.
You can have multidimensional dicts also without the lists, e.g.:
ConsomRatio = {}
ConsomRation["DAP_Local"] = {"Ammonia":"0.229", "Amine":"0.0007"}
ConsomRatio["MAP11_52"] = {"Ammonia":"0.138", "Fuel":"0.003"}
print(ConsomRatio["DAP_Local"]["Ammonia"])
will give the desired result without the extra effort with the list.
You can get even shorter in Python:
ConsomRatio = {
"DAP_Local": {"Ammonia":"0.229", "Amine":"0.0007"},
"MAP11_52" : {"Ammonia":"0.138", "Fuel":"0.003"},
}
print(ConsomRatio["DAP_Local"]["Ammonia"])
To also answer your latest question (in your second comment):
to_produce = 'DAP_Local'
ingredience = 'Ammonia'
print('To produce {to_produce} we need {amount} of {ingredience}'.format(
to_produce=to_produce, ingredience=ingredience,
amount=ConsomRatio[to_produce].get(ingredience, '0.0')))
I hope, that helps!
It gets even better:
for product, ingred_list in ConsomRatio.items():
for iname, ivalue in ingred_list.items():
print('To produce {to_produce} we need {amount} of {ingredience}'
.format(to_produce=product, ingredience=iname,
amount=ivalue))
I have the two following lists:
# List of tuples representing the index of resources and their unique properties
# Format of (ID,Name,Prefix)
resource_types=[('0','Group','0'),('1','User','1'),('2','Filter','2'),('3','Agent','3'),('4','Asset','4'),('5','Rule','5'),('6','KBase','6'),('7','Case','7'),('8','Note','8'),('9','Report','9'),('10','ArchivedReport',':'),('11','Scheduled Task',';'),('12','Profile','<'),('13','User Shared Accessible Group','='),('14','User Accessible Group','>'),('15','Database Table Schema','?'),('16','Unassigned Resources Group','#'),('17','File','A'),('18','Snapshot','B'),('19','Data Monitor','C'),('20','Viewer Configuration','D'),('21','Instrument','E'),('22','Dashboard','F'),('23','Destination','G'),('24','Active List','H'),('25','Virtual Root','I'),('26','Vulnerability','J'),('27','Search Group','K'),('28','Pattern','L'),('29','Zone','M'),('30','Asset Range','N'),('31','Asset Category','O'),('32','Partition','P'),('33','Active Channel','Q'),('34','Stage','R'),('35','Customer','S'),('36','Field','T'),('37','Field Set','U'),('38','Scanned Report','V'),('39','Location','W'),('40','Network','X'),('41','Focused Report','Y'),('42','Escalation Level','Z'),('43','Query','['),('44','Report Template ','\\'),('45','Session List',']'),('46','Trend','^'),('47','Package','_'),('48','RESERVED','`'),('49','PROJECT_TEMPLATE','a'),('50','Attachments','b'),('51','Query Viewer','c'),('52','Use Case','d'),('53','Integration Configuration','e'),('54','Integration Command f'),('55','Integration Target','g'),('56','Actor','h'),('57','Category Model','i'),('58','Permission','j')]
# This is a list of resource ID's that we do not want to reference directly, ever.
unwanted_resource_types=[0,1,3,10,11,12,13,14,15,16,18,20,21,23,25,27,28,32,35,38,41,47,48,49,50,57,58]
I'm attempting to compare the two in order to build a third list containing the 'Name' of each unique resource type that currently exists in unwanted_resource_types. e.g. The final result list should be:
result = ['Group','User','Agent','ArchivedReport','ScheduledTask','...','...']
I've tried the following that (I thought) should work:
result = []
for res in resource_types:
if res[0] in unwanted_resource_types:
result.append(res[1])
and when that failed to populate result I also tried:
result = []
for res in resource_types:
for type in unwanted_resource_types:
if res[0] == type:
result.append(res[1])
also to no avail. Is there something i'm missing? I believe this would be the right place to perform list comprehension, but that's still in my grey basket of understanding fully (The Python docs are a bit too succinct for me in this case).
I'm also open to completely rethinking this problem, but I do need to retain the list of tuples as it's used elsewhere in the script. Thank you for any assistance you may provide.
Your resource types are using strings, and your unwanted resources are using ints, so you'll need to do some conversion to make it work.
Try this:
result = []
for res in resource_types:
if int(res[0]) in unwanted_resource_types:
result.append(res[1])
or using a list comprehension:
result = [item[1] for item in resource_types if int(item[0]) in unwanted_resource_types]
The numbers in resource_types are numbers contained within strings, whereas the numbers in unwanted_resource_types are plain numbers, so your comparison is failing. This should work:
result = []
for res in resource_types:
if int( res[0] ) in unwanted_resource_types:
result.append(res[1])
The problem is that your triples contain strings and your unwanted resources contain numbers, change the data to
resource_types=[(0,'Group','0'), ...
or use int() to convert the strings to ints before comparison, and it should work. Your result can be computed with a list comprehension as in
result=[rt[1] for rt in resource_types if int(rt[0]) in unwanted_resource_types]
If you change ('0', ...) into (0, ... you can leave out the int() call.
Additionally, you may change the unwanted_resource_types variable into a set, like
unwanted_resource_types=set([0,1,3, ... ])
to improve speed (if speed is an issue, else it's unimportant).
The one-liner:
result = map(lambda x: dict(map(lambda a: (int(a[0]), a[1]), resource_types))[x], unwanted_resource_types)
without any explicit loop does the job.
Ok - you don't want to use this in production code - but it's fun. ;-)
Comment:
The inner dict(map(lambda a: (int(a[0]), a[1]), resource_types)) creates a dictionary from the input data:
{0: 'Group', 1: 'User', 2: 'Filter', 3: 'Agent', ...
The outer map chooses the names from the dictionary.
I'm playing with both learning Python and am trying to get GitHub issues into a readable form. Using the advice on How can I convert JSON to CSV?, I came up with this:
import json
import csv
f = open('issues.json')
data = json.load(f)
f.close()
f = open("issues.csv", "wb+")
csv_file = csv.writer(f)
csv_file.writerow(["gravatar_id", "position", "number", "votes", "created_at", "comments", "body", "title", "updated_at", "html_url", "user", "labels", "state"])
for item in data:
csv_file.writerow([item["gravatar_id"], item["position"], item["number"], item["votes"], item["created_at"], item["comments"], item["body"], item["title"], item["updated_at"], item["html_url"], item["user"], item["labels"], item["state"]])
Where "issues.json" is the JSON file containing my GitHub issues. When I try to run that, I get
File "foo.py", line 14, in <module>
csv_file.writerow([item["gravatar_id"], item["position"], item["number"], item["votes"], item["created_at"], item["comments"], item["body"], item["title"], item["updated_at"], item["html_url"], item["user"], item["labels"], item["state"]])
TypeError: string indices must be integers
What am I missing here? Which are the "string indices"? I'm sure that once I get this working I'll have more issues, but for now, I'd just love for this to work!
When I tweak the for statement to simply
for item in data:
print item
what I get is ... "issues" -- so I'm doing something more basic wrong. Here's a bit of my JSON content:
{"issues": [{"gravatar_id": "44230311a3dcd684b6c5f81bf2ec9f60", "position": 2.0, "number": 263, "votes": 0, "created_at": "2010/09/17 16:06:50 -0700", "comments": 11, "body": "Add missing paging (Older>>) links...
when I print data, it looks like it is getting munged really oddly:
{u'issues': [{u'body': u'Add missing paging (Older>>) lin...
The variable item is a string. An index looks like this:
>>> mystring = 'helloworld'
>>> print mystring[0]
'h'
The above example uses the 0 index of the string to refer to the first character.
Strings can't have string indices (like dictionaries can). So this won't work:
>>> mystring = 'helloworld'
>>> print mystring['stringindex']
TypeError: string indices must be integers
item is most likely a string in your code; the string indices are the ones in the square brackets, e.g., gravatar_id. So I'd first check your data variable to see what you received there; I guess that data is a list of strings (or at least a list containing at least one string) while it should be a list of dictionaries.
TypeError for Slice Notation str[a:b]
Short Answer
Use a colon : instead of a comma , in between the two indices a and b in str[a:b]:
my_string[0,5] # wrong ❌
my_string[0:5] # correct ✅
Long Answer
When working with strings and slice notation (a common sequence operation), it can happen that a TypeError is raised, pointing out that the indices must be integers, even if they obviously are.
Example
>>> my_string = "Hello, World!"
>>> my_string[0,5]
TypeError: string indices must be integers
We obviously passed two integers for the indices to the slice notation, right? So what is the problem here?
This error can be very frustrating - especially at the beginning of learning Python - because the error message is a little bit misleading.
Explanation
We implicitly passed a tuple of two integers to the slice notation when we called my_string[0,5]. 0,5 evaluates to the same tuple as (0,5) does - even without the parentheses. Why though?
A trailing comma , is actually enough for the Python interpreter to evaluate something as a tuple:
>>> my_variable = 0,
>>> type(my_variable)
<class 'tuple'>
So what we did there, this time explicitly:
>>> my_string = "Hello, World!"
>>> my_tuple = 0, 5
>>> my_string[my_tuple]
TypeError: string indices must be integers
Now, at least, the error message makes sense.
Solution
We need to replace the comma , with a colon : to separate the two integers correctly, not having them interpreted as a tuple:
>>> my_string = "Hello, World!"
>>> my_string[0:5]
'hello'
A clearer and more helpful error message could have been something like:
TypeError: string indices must be integers not tuple
^^^^^
(actual type here)
A good error message should show the user directly what they did wrong! With this kind of information it would have been much more easier to find the root cause and solve the problem - and you wouldn't have had to come here.
So next time, when you find yourself responsible for writing error description messages, remind yourself of this example and add the reason (or other useful information) to error message! Help other people (or maybe even your future self) to understand what went wrong.
Lessons learned
slice notation uses colons : to separate its indices (and step range, i.e., str[from:to:step])
tuples are defined by commas , (i.e., t = 1,)
add some information to error messages for users to understand what went wrong
data is a dict object. So, iterate over it like this:
Python 2
for key, value in data.iteritems():
print key, value
Python 3
for key, value in data.items():
print(key, value)
I had a similar issue with Pandas, you need to use the iterrows() function to iterate through a Pandas dataset Pandas documentation for iterrows
data = pd.read_csv('foo.csv')
for index,item in data.iterrows():
print('{} {}'.format(item["gravatar_id"], item["position"]))
note that you need to handle the index in the dataset that is also returned by the function.
As a rule of thumb, when I receive this error in Python I compare the function signature with the function execution.
For example:
def print_files(file_list, parent_id):
for file in file_list:
print(title: %s, id: %s' % (file['title'], file['id']
So if I'll call this function with parameters placed in the wrong order and pass the list as the 2nd argument and a string as the 1st argument:
print_files(parent_id, list_of_files) # <----- Accidentally switching arguments location
The function will try to iterate over the parent_id string instead of file_list and it will expect to see the index as an integer pointing to the specific character in string and not an index which is a string (title or id).
This will lead to the TypeError: string indices must be integers error.
Due to its dynamic nature (as opposed to languages like Java, C# or Typescript), Python will not inform you about this syntax error.
How to read the first element of this JSON?
when the file appears like this
for i in data[1]:
print("Testing"+i['LocalObservationDateTime'])
This is not working for me.
Below is the JSON file
[
{
"LocalObservationDateTime":"2022-09-15T19:05:00+02:00",
"EpochTime":1663261500,
"WeatherText":"Mostly cloudy",
"WeatherIcon":6,
"HasPrecipitation":false,
"PrecipitationType":"None",
"IsDayTime":true,
"Temperature":{
"Metric":{
"Value":11.4,
"Unit":"C",
"UnitType":17
},
"Imperial":{
"Value":52.0,
"Unit":"F",
"UnitType":18
}
},
"RealFeelTemperature":{
"Metric":{
"Value":8.4,
"Unit":"C",
"UnitType":17,
"Phrase":"Chilly"
}
}
},
{
"LocalObservationDateTime":"2022-09-16T19:05:00+02:00",
"EpochTime":1663261500,
"WeatherText":"Mostly cloudy",
"WeatherIcon":6,
"HasPrecipitation":false,
"PrecipitationType":"None",
"IsDayTime":true,
"Temperature":{
"Metric":{
"Value":11.4,
"Unit":"C",
"UnitType":17
},
"Imperial":{
"Value":52.0,
"Unit":"F",
"UnitType":18
}
},
"RealFeelTemperature":{
"Metric":{
"Value":8.4,
"Unit":"C",
"UnitType":17,
"Phrase":"Chilly"
}
}
}
]
This can happen if a comma is missing. I ran into it when I had a list of two-tuples, each of which consisted of a string in the first position, and a list in the second. I erroneously omitted the comma after the first component of a tuple in one case, and the interpreter thought I was trying to index the first component.
Converting the lower case letters to upper:
str1 = "Hello How are U"
new_str = " "
for i in str1:
if str1[i].islower():
new_str = new_str + str1[i].upper()
print(new_str)
Error :
TypeError: string indices must be integers
Solution :
for i in range(0, len(str1))
// Use range while iterating the string.