My code is as follows with comments. it runs fine until it comes to changing the value of a list item i.e. data[x][y] = something.
Tdata = cursor.fetchall() #Get data from MYSQL database
data = list(Tdata) #Convert into list...not sure if absolutely required
APIData = APIDataList()
MPLlat = 0.0
MPLLon = 0.0
RadiusOI = 15
for i in (range(0,len(data))):
MPLCount = 0
MPLlat = data[i][2]
MPLLon = data[i][3]
MPLCount = CountofbikesnearMPL(MPLlat, MPLLon, RadiusOI)
if MPLCount>0:
data[i][4] = MPLCount #ERROR: here is where the error is kicking in.
#get error "tuple' object does not support
#item assignment"
I really cant figure out why this is happening and have tried googling but with no success. Any help will be deeply appreciated.
Thanks in advance.
C
cursor.fetchall() returns a list of tuples.
That means that data[i] will be a tuple, which is by definition immutable. If you want to modify data[i], you will need to turn your tuples into lists
data = [list(row) for row in Tdata]
or replace the entire row via tuple concatenation
data[i] = data[i][:4] + (MPLCount,) + data[i][5:]
Maybe it is cleaner to write it using enumerate:
for i, elem in enumerate(data):
# MPLCount = 0 - I suppose it is unnecessary since you overwrite the value below
MPLlat = elem[2]
MPLLon = elem[3]
MPLCount = CountofbikesnearMPL(MPLlat, MPLLon, RadiusOI)
if MPLCount > 0:
data[i] = elem[:4] + (MPLCount,) + elem[5:]
Is there a reason you name variables and functions ThisWay? If not, it would be nice if you follow PEP8 and name them this_way. Anyway be consistent and don't mix two styles together.
Related
In line 52 of my code I keep getting the error, fact_check.py:52: [C0206(consider-using-dict-items), get_totals] Consider iterating with .items() and I don't know how to fix it. the section of code is as follows...
def get_totals(data, presidents):
'''
Description: Takes a list of raw data, and a dictionary of years adn the associated president.
It then creates an output list, with the total jobs and their associated president
Requires: List data, Dictionary presidents
Returns: List output
'''
output = []
pre_output = {}
for i in data:
i[0] = int(i[0])
try:
pre_output[presidents[i[0] - 1]].append(i[1])
pre_output[presidents[i[0]]].extend(i[1: ])
except KeyError:
pre_output[presidents[i[0]]] = []
pre_output[presidents[i[0]]].extend(i[1: ])
for i in pre_output: # <---- (line 52)
k = pre_output[i]
tmp_list = [i]
before = int(k[0])
total = 0
j = _
for j in k:
if j == '':
continue
j = int(j)
total += j - before
before = j
tmp_list.append(total)
output.append(tmp_list)
return output
Haven't tried much because honestly I don't know why its doing this. Any information helps.
That's not an error, and it was not issued by Python. You can replace those first two statements with for i,k in pre_output.items(): and get both at once.
-- Comment by Tim Roberts
After making a post and receiving the return I want to treat him.
lambdaGetDependencies returns a JSON and I need specific values from the JSON, that's what I try to do inside the cycle.
if CLUSTER_ENDPOINT and CLUSTER_PORT:
data = lambdaGetDependencies(resource)
else:
print("provide CLUSTER_ENDPOINT and CLUSTER_PORT environment variables")
elements = data['result']['data']['#value']
dependencies = [None] * len(elements)
count = 0
j = 0
for i in elements:
while j < len(i['#value']):
x = {i['#value'][j]: i['#value'][j+1]['#value'][0]}
c.append(x)
dependencies[count] = i['#value'][j+1]['#value'][0]
count += 1
j += 1
return json.dumps(c)
The problem is that I get string indices must be integers on the line:
x = {i['#value'][j]: i['#value'][j+1]['#value'][0]}
and I don't get why. Any ideas?
i['#value'][j+1] is probably a string and not a dictionary. If that is the case then this i['#value'][j+1]['#value'][0] is invalid.
Goal is to replace the second field of csv_line with new_item in an elegant way. This question is different from the topics listed by Rawing because here we are working with a different data structure, though we can use other topics to get inspired.
# Please assume that csv_line has not been imported from a file.
csv_line = 'unknown_item1,unknown_old_item2,unknown_item3'
new_item = 'unknown_new_item2'
goal = 'unknown_item1,unknown_new_item2,unknown_item3'
# Works but error prone. Non-replaced items could be inadvertently swapped.
# In addition, not convenient if string has many fields.
item1, item2, item3 = csv_line.split(',')
result = ','.join([item1, new_item, item3])
print(result) # unknown_item1,unknown_new_item2,unknown_item3
# Less error prone but ugly.
result_list = []
new_item_idx = 1
for i, item in enumerate(csv_line.split(',')):
result_list += [item] if i != new_item_idx else [new_item]
result = ','.join(result_list)
print(result) # unknown_item1,unknown_new_item2,unknown_item3
# Ideal (not-error prone) but not working.
csv_line.split(',')[1] = new_item
print(csv_line) # unknown_item1,unknown_old_item2,unknown_item3
The second item could be replaced using Python's CSV library by making use of io.StringIO() objects. This behave like files but can be read as a string:
import csv
import io
csv_line = 'unknown_item1,unknown_old_item2,unknown_item3'
new_item = 'unknown_new_item2'
row = next(csv.reader(io.StringIO(csv_line)))
row[1] = new_item
output = io.StringIO()
csv.writer(output).writerow(row)
goal = output.getvalue()
print(goal)
This would display goal as:
unknown_item1,unknown_new_item2,unknown_item3
l = csv_line.split(',')
l[1] = new_item
csv_line = ','.join(l)
In the line csv_line.split(',')[1] = new_item, you do not alter the csv_line variable at all. You need to assign the new list created with .split() to a variable before you can change the elements within it:
new_csv = csv_line.split(',')
new_csv[1] = new_item
print(','.join(new_csv))
This seems the most pythonic:
csv_line = 'unknown_item1,old_item2,unknown_item3'
old_index = 1
new_item = 'new_item2'
goal = 'unknown_item1,new_item2,unknown_item3'
items = csv_line.split(',')
items[old_index] = new_item
print(','.join(items))
print(goal)
Output:
unknown_item1,new_item2,unknown_item3
unknown_item1,new_item2,unknown_item3
I'm new to python. I'm creating 2 arrays file_name(stores name of the files) and path(stores paths of files). Values of path array are assigned inside while loop. But I'm getting the error:
IndexError: list assignment index out of range in Python
I had already wasted several hours on this one, but haven't got the output as I expected. So, can you please let me know where I have made the mess? Any help will be highly appreciated. Thanks in advance.
My Code:
file_name = ['abc','xyz','pqr','mno','def','ghi','rst','uvw','jkl']
path = []
count = 0
while count < 9:
path[count] = "D:\\Work\\"+file_name[count]+".csv"
print (path[count])
count = count + 1
Expected Output:
D:\\Work\\abc.csv
D:\\Work\\xyz.csv
D:\\Work\\pqr.csv
D:\\Work\\mno.csv
D:\\Work\\def.csv
D:\\Work\\ghi.csv
D:\\Work\\rst.csv
D:\\Work\\uvw.csv
D:\\Work\\jkl.csv
You can't access path[count] and assign something to it if path[count] doesn't already exist.
To create a new list, use .append(). You don't need to keep track of a counter at all (it's rarely necessary to do a C-style loop in Python; the pythonic way is to iterate over the elements of a list/tuple/dictionary directly):
file_name = ['abc','xyz','pqr','mno','def','ghi','rst','uvw','jkl']
path = []
for item in file_name:
newpath = "D:\\Work\\" + item + ".csv"
# or better: newpath = r"D:\Work\{}.csv".format(item)
path.append(newpath)
print(newpath)
You are looking for the append method.
file_name = ['abc','xyz','pqr','mno','def','ghi','rst','uvw','jkl']
path = []
count = 0
while count < 9:
path.append("D:\\Work\\"+file_name[count]+".csv")
print (path[count])
count = count + 1
You will get your expected output.
You need to append an item to the list. It would look like that then:
file_name = ['abc','xyz','pqr','mno','def','ghi','rst','uvw','jkl']
path = []
count = 0
while count < 9:
path.append("D:\\Work\\"+file_name[count]+".csv")
print (path[count])
count = count + 1
Since when you created an empty list, it had no items, thus accessing it via index didn't work. You can also skip the while loop and use some Python sugar to get the same effect:
file_name = ['abc','xyz','pqr','mno','def','ghi','rst','uvw','jkl']
path = ['D:\\Work\\' + x + '.csv' for x in file_name]
for p in path:
print(p)
I have a nested list comprehension which has created a list of six lists of ~29,000 items. I'm trying to parse this list of final data, and create six separate dictionaries from it. Right now the code is very unpythonic, I need the right statement to properly accomplish the following:
1.) Create six dictionaries from a single statement.
2.) Scale to any length list, i.e., not hardcoding a counter shown as is.
I've run into multiple issues, and have tried the following:
1.) Using while loops
2.) Using break statements, will break out of the inner most loop, but then does not properly create other dictionaries. Also break statements set by a binary switch.
3.) if, else conditions for n number of indices, indices iterate from 1-29,000, then repeat.
Note the ellipses designate code omitted for brevity.
# Parse csv files for samples, creating a dictionary of key, value pairs and multiple lists.
with open('genes_1') as f:
cread_1 = list(csv.reader(f, delimiter = '\t'))
sample_1_values = [j for i, j in (sorted([x for x in {i: float(j)
for i, j in cread_1}.items()], key = lambda v: v[1]))]
sample_1_genes = [i for i, j in (sorted([x for x in {i: float(j)
for i, j in cread_1}.items()], key = lambda v: v[1]))]
...
# Compute row means.
mean_values = []
for i, (a, b, c, d, e, f) in enumerate(zip(sample_1_values, sample_2_values, sample_3_values, sample_4_values, sample_5_values, sample_6_values)):
mean_values.append((a + b + c + d + e + f)/6)
# Provide proper gene names for mean values and replace original data values by corresponding means.
sample_genes_list = [i for i in sample_1_genes, sample_2_genes, sample_3_genes, sample_4_genes, sample_5_genes, sample_6_genes]
sample_final_list = [sorted(zip(sg, mean_values)) for sg in sample_genes_list]
# Create multiple dictionaries from normalized values for each dataset.
class BreakIt(Exception): pass
try:
count = 1
for index, items in enumerate(sample_final_list):
sample_1_dict_normalized = {}
for index, (genes, values) in enumerate(items):
sample_1_dict_normalized[genes] = values
count = count + 1
if count == 29595:
raise BreakIt
except BreakIt:
pass
...
try:
count = 1
for index, items in enumerate(sample_final_list):
sample_6_dict_normalized = {}
for index, (genes, values) in enumerate(items):
if count > 147975:
sample_6_dict_normalized[genes] = values
count = count + 1
if count == 177570:
raise BreakIt
except BreakIt:
pass
# Pull expression values to qualify overexpressed proteins.
print 'ERG values:'
print 'Sample 1:', round(sample_1_dict_normalized.get('ERG'), 3)
print 'Sample 6:', round(sample_6_dict_normalized.get('ERG'), 3)
Your code is too long for me to give exact answer. I will answer very generally.
First, you are using enumerate for no reason. if you don't need both index and value, you probably don't need enumerate.
This part:
with open('genes.csv') as f:
cread_1 = list(csv.reader(f, delimiter = '\t'))
sample_1_dict = {i: float(j) for i, j in cread_1}
sample_1_list = [x for x in sample_1_dict.items()]
sample_1_values_sorted = sorted(sample_1_list, key=lambda expvalues: expvalues[1])
sample_1_genes = [i for i, j in sample_1_values_sorted]
sample_1_values = [j for i, j in sample_1_values_sorted]
sample_1_graph_raw = [float(j) for i, j in cread_1]
should be (a) using a list named samples and (b) much shorter, since you don't really need to extract all this information from sample_1_dict and move it around right now. It can be something like:
samples = [None] * 6
for k in range(6):
with open('genes.csv') as f: #but something specific to k
cread = list(csv.reader(f, delimiter = '\t'))
samples[k] = {i: float(j) for i, j in cread}
after that, calculating the sum and mean will be way more natural.
In this part:
class BreakIt(Exception): pass
try:
count = 1
for index, items in enumerate(sample_final_list):
sample_1_dict_normalized = {}
for index, (genes, values) in enumerate(items):
sample_1_dict_normalized[genes] = values
count = count + 1
if count == 29595:
raise BreakIt
except BreakIt:
pass
you should be (a) iterating of the samples list mentioned earlier, and (b) not using count at all, since you can iterate naturally over samples or sample[i].list or something like that.
Your code has several problems. You should put your code in functions that preferably do one thing each. Than you can call a function for each sample without repeating the same code six times (I assume that is what the ellipsis is hiding.). Give each function a self-describing name and a doc string that explains what it does. There is quite a bit unnecessary code. Some of this might become obvious once you have it in functions. Since functions take arguments you can hand in your 29595, for example.