I have a db query that returns tuple as below
[6,6,6,5,5,5,4,4]
[10,10,10,11,11,11]
[3597590, 3597588,3597558,3597544,3597590]
I would like to get the average of each set. I tried to sum them using different ways for example
for row in cur.fetchall(
x = row[4]
print map(sum, x)
it throws an error
TypeError: unsupported operand type(s) for +: 'int' and 'str'
I try to convert to int but also throws error
ValueError: invalid literal for int() with base 10: '['
looks like you have a string representing a list of integers, in that case you can use the ast module, more precisely the ast.literal_eval function to transform it to an actual list and sum it
>>> import ast
>>> test = "[3597590, 3597588,3597558,3597544,3597590]"
>>> x=ast.literal_eval(test)
>>> x
[3597590, 3597588, 3597558, 3597544, 3597590]
>>> sum(x)
17987870
>>>
if what you get is a string that looks as your example, then you can use the splitlines method to get each line
>>> test2="""[6,6,6,5,5,5,4,4]
[10,10,10,11,11,11]
[3597590, 3597588,3597558,3597544,3597590]"""
>>> lines = test2.splitlines()
>>> lines
['[6,6,6,5,5,5,4,4]', '[10,10,10,11,11,11]', '[3597590, 3597588,3597558,3597544,3597590]']
>>> map(sum,map(ast.literal_eval,lines))
[41, 63, 17987870]
>>>
as mention in the comments, the json module is another option
>>> import json
>>> test
'[3597590, 3597588,3597558,3597544,3597590]'
>>> json.loads(test)
[3597590, 3597588, 3597558, 3597544, 3597590]
>>>
The answer from #Copperfield is likely the right way to do it for the problem as stated.
That said, I think you should deal with the problem upstream rather than in Python. Use the SQL SUM and AVERAGE functions inside your query so that the work is done by the SQL engine.
Related
So I have written a function which reads a file (csv) and returns the average of each line of numbers, as a list.
I believe the code should work however I have tried many ways and cant get the data to convert to numerical values(that can then be summed etc.) from a list.
def line_averages(filename):
file = open(filename, 'r')
data = file.readlines()
file.close()
x = []
for i in data:
data_splitted = i.split()
line_average = sum(data_splitted) / len(data_splitted)
x.append(line_average)
return x
specifically when I run this with my file I get:
<class '_io.TextIOWrapper'>
Traceback (most recent call last):
File "<ipython-input-100-426fb6997e94>", line 1, in <module>
line_averagesTEST(e)
File "C:/Users/liver/Documents/Python Practise/lab4.py", line 32, in line_averagesTEST
line_average = sum(split) / len(split)
TypeError: unsupported operand type(s) for +: 'int' and 'str'
sorry if an easy fix as I am new to this lol
So, it looks live you've realized the source of your error is that your list contains strings instead of a numeric data type, which is why addition won't work. The naive way to do this (a perfectly reasonable one I might add), is to simply loop:
>>> total = 0
>>> for x in split:
... total += float(x)
...
>>> total
17.0
OK, we didn't use the sum function. Would could also do something like:
>>> split_f = []
>>> for x in split:
... split_f.append(float(x))
...
>>> sum(split_f)
17.0
This also works fine, although, it creates an unecessary intermediate list. But note the pattern from the above two loops: you apply the same function over-and-over to each element in the list, i.e. you map the function onto the list. Well, Python is batteries included:
>>> sum(map(float, split))
17.0
Note, on Python3, the above solution doesn't create an unecessary intermediate list!
How is your data in the file arrange? I think you should use the delimiter as an argument in your split function. For instance if you file contains lines like:
1,2,3,4...
you must use i.split(",").
When data is split correctly you could use numpy and a notation like that to easily calculate the average
line_average = np.mean([float(a) for a in data_splitted])
and you have to put
import numpy as np
at the beginning of your function.
You read in string data, split it into sub-strings, and then try to sum the strings. You have to convert the input to numeric types before you can add them.
This is a code for format printing multiple lists:
print("{0[0]:10s} {1[0]:20} {2[0]:5} £{3[0]:6} £{4[0]:<7}".format(gtinlist, desclist, qtylist, pricelist, valuelist))
This prints the first value of each list
But as soon as I change it to:
print("{0[0:9]:10s} {1[0:9]:20} {2[0:9]:5} £{3[0:9]:6} £{4[0:9]:<7}".format(gtinlist, desclist, qtylist, pricelist, valuelist))
And if I put any number in the place of :9 it does not work.
I don't understand why
Help?
If you want to print the 9th position, you can use
"{0[8]:10s}"
Using
"{0[0:9]:10s}"
will tell format() to use the key "0:9", which is a string but lists only have integer keys:
TypeError: list indices must be integers or slices, not str).
In python derp[0:9] means, to get a slice of the list derp from key 0 to key 8. But format() does not interpret the 0:9 as python syntax. Format does check if the instance has a __getitem__ method and passes the key to it.
>>> class donk():
... def __getitem__(self, k):
... return 5
...
>>> a = donk()
>>> 'bla{0[3]}'.format(a)
'bla5'
If you want to print the first 8 elements here, maybe separated by comma, you may use:
", ".join(['{:10s}'.format(a) for a in my_list[0:9])
Additional: If you want to print all stuff in your arrays on separate lines you can use a for-loop:
for i, gt in enumerate(gtinlist):
print("{:10s} {:20} {:5} £{:6} £{:<7}".format(gt, desclist[i], stylist[i], priceless[i], valueless[i]))
In this approach len(gtinlist) <= len(stylist), len(priceless), len(valueless)
Apparently slicing isn't supported there, only integers (which are turned into ints) and everything else will be interpreted as a string index:
>>> class Foo:
def __getitem__(self, index):
print('got asked for:', type(index).__name__, repr(index))
>>> x = '{0[3]}'.format(Foo())
got asked for: int 3
>>> x = '{0[3:7]}'.format(Foo())
got asked for: str '3:7'
How it would look if a slice were requested:
>>> Foo()[3:7]
got asked for: slice slice(3, 7, None)
I checked the docs but couldn't really find an answer, just that "an expression of the form '[index]' does an index lookup using __getitem__()", which could support slicing. But it doesn't even mention that integers will be turned into ints.
The following is the list that I have:
>>> issue_search
[<JIRA Issue: key=u'NEC-1519', id=u'991356'>, <JIRA Issue: key=u'NEC-1516', id=u'991344'>, <JIRA Issue: key=u'NEC-1518', id=u'990463'>]
>>>
I was using the following:
issue_string = ','.join(map(str, issue_search))
But the output is:
NEC-1519, NEC-1516, NEC-1518
I am confused on the output. How is only the key getting displayed? How to get the other text too in the string format?
What you see in the list is the values returned by each object's __repr__ method. If you want these values, map the list to repr instead of str:
issue_string = ','.join(map(repr, issue_search))
Below is a demonstration with decimal.Decimal:
>>> from decimal import Decimal
>>> lst = [Decimal('1.2'), Decimal('3.4'), Decimal('5.6')]
>>> lst
[Decimal('1.2'), Decimal('3.4'), Decimal('5.6')]
>>> print ','.join(map(str, lst))
1.2,3.4,5.6
>>> print ','.join(map(repr, lst))
Decimal('1.2'),Decimal('3.4'),Decimal('5.6')
>>>
You are calling str on the objects within issue_search before joining them. So obviously, the call of str on a “JIRA Issue” will only result in the key.
The return value of str is determined by an object’s __str__ method which is likely defined in the described way for the “JIRA Issue” type. If you cannot change the method, you could also call repr on the objects instead, or specify a custom format function:
>>> ', '.join(map(lambda x: '{} ({})'.format(x.key, x.id), issue_search))
'NEC-1519 (991356), NEC-1516 (991344), NEC-1518 (990463)'
a'$'
money=1000000;
portfolio=0;
value=0;
value=(yahoostock.get_price('RIL.BO'));
portfolio=(16*(value));
print id(portfolio);
print id(value);
money= (money-portfolio);
'''
I am getting the error:
Traceback (most recent call last):
File "/home/dee/dee.py", line 12, in <module>
money= (value-portfolio);
TypeError: unsupported operand type(s) for -: 'str' and 'str'
Since money is integer and so is portfolio, I cant solve this problem..anyone can help???
value=(yahoostock.get_price('RIL.BO'));
Apparently returns a string not a number. Convert it to a number:
value=int(yahoostock.get_price('RIL.BO'));
Also the signal-to-noise ratio isn't very high. You've lots of (,), and ; you don't need. You assign variable only to replace them on the next line. You can make your code nicer like so:
money = 1000000
value = int(yahoostock.get_price('RIL.BO'));
portfolio = 16 * value;
print id(portfolio);
print id(value);
money -= portfolio;
money and portfolio are apparently strings, so cast them to ints:
money= int( float(money)-float(portfolio) )
As the error message clearly states, both are string, cast with int(var).
Note:
Let's see what can we decude from the error message:
portfolio must be string(str), which means value is also a string. Like this:
>>> 16*"a"
'aaaaaaaaaaaaaaaa'
and apparently you missed to post relevant code because the error message tells you that money is str as well.
I think the problem here is assuming that because you have initialised variables with integer values they will remain as integers. Python doesn't work this way. Assigning a value with = only binds the name to the value without paying any attention to type. For example:
a = 1 # a is an int
a = "Spam!" # a is now a str
I assume yahoostock.getprice(), like many functions that get data from websites, returns a string. You need to convert this using int() before doing your maths.
abc = {}
abc[int: anotherint]
Then the error came up. TypeError: unhashable type? Why I received this?
I've tried str()
This seems to be a syntax issue:
>>> abc = {}
>>> abc[1] = 2
>>> abc
{1: 2}
>>> abc = {1:2, 3:4}
>>> abc
{1: 2, 3: 4}
>>>
At least the syntax of following is incorrect
abc[int: anotherint]
I guess you want to say
abc = [int: anotherint]
Which is incorrect too. The correct way is
abc = {int: anotherint}
unless abc is already defined in which case:
abc[int] = anotherint
is also a valid option.
There are two things wrong - first you have a logic error - I really don't think you want the slice of the dictionary between int (the type, which is unhashable [see below]) and the number anotherInt. Not of course that this is possible in python, but that is what you are saying you want to do.
Second, assuming you meant x[{int:anotherInt}]:
What that error means is that you can't use that as a key in a dictionary, as a rule python doesn't like you using mutable types as keys in dictionaries - it complicates things if you later add stuff to the dictionary or list... consider the following very confusing example:
x={}
x[x]=1
what would you expect this to do, if you tried to subscript that array which would you expect to return 1?
x[{}]
x[{x:x}]
x[{{}:x}]
x[x]
basicly when hashing mutable types you can either say, {} != {} with respect to hashes because they are stored in different places in memory or you end up with the weird recursive situation above
Since the title says appending and none of the answers provided a solution to append things to the dictionary I give it a try:
abc = {}
abc[1]= 2
abc['a'] = [3,9,27]
==> abc = {1:2, 'a':[3,9,27]}