Why reduce function asking for arguments - python-3.x

I have written these lines of code with reduce built in function but it show an error for given arguments.
Error:
TypeError Traceback (most recent call last)
in
4
5 lst = [1,2,3]
----> 6 reduce(d_n, lst)
TypeError: d_n() takes 1 positional argument but 2 were given
from functools import reduce
def d_n(digit):
return(digit)
lst = [1,2,3]
reduce(d_n, lst)

reduce(...)
reduce(function, sequence[, initial]) -> value
Apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
((((1+2)+3)+4)+5). If initial is present, it is placed before the items
of the sequence in the calculation, and serves as a default when the
sequence is empty.
Key point: a function of two arguments
Your d_n() function takes only one argument, which makes it incompatible with reduce

Related

Cannot create a numpy array using numpy's `full()` method and a python list

I can create a numpy array from a python list as follows:
>>> a = [1,2,3]
>>> b = np.array(a).reshape(3,1)
>>> print(b)
[[1]
[2]
[3]]
However, I don't know what causes error in the following code:
Code :
>>> a = [1,2,3]
>>> b = np.full((3,1), a)
Error :
ValueError Traceback (most recent call last)
<ipython-input-275-1ab6c109dda4> in <module>()
1 a = [1,2,3]
----> 2 b = np.full((3,1), a)
3 print(b)
/usr/local/lib/python3.6/dist-packages/numpy/core/numeric.py in full(shape, fill_value, dtype, order)
324 dtype = array(fill_value).dtype
325 a = empty(shape, dtype, order)
--> 326 multiarray.copyto(a, fill_value, casting='unsafe')
327 return a
328
<__array_function__ internals> in copyto(*args, **kwargs)
ValueError: could not broadcast input array from shape (3) into shape (3,1)
Even though the list a has 3 elements inside it and I expect a 3x1 numpy array, the full() method fails to deliver it.
I referred the broadcasting article of numpy too. However, they are much more focused towards the arithmetic operation perspective, hence I couldn't obtain anything useful from there.
So it would be great if you can help me to understand the difference in b/w. the above mentioned array creation methods and the cause of the error too.
Numpy is unable to broadcast the two shapes together because your list is interpreted as a 'row vector' (np.array(a).shape = (3,)) while you are asking for a 'column vector' (shape = (3, 1)). If you are set on using np.full, then you can shape your list as a column vector initially:
>>> import numpy as np
>>>
>>> a = [[1],[2],[3]]
>>> b = np.full((3,1), a)
Another option is to convert a into a numpy array ahead of time and add a new axis to match the desired output shape.
>>> a = [1,2,3]
>>> a = np.array(a)[:, np.newaxis]
>>> b = np.full((3,1), a)

Perform a frequency distribution count on a generator, and return values that are greater than n

Is there a way to perform a count on a generator object that is pointing to a list of lists? If so, can I make the count operation output a generator object (of counted items) of previous generator object? I then would like to get a frequency count. I am using generators to conserve memory and prevent crashes. My real data set/list is enormous!
I have a generator object, 'gen_list', created from a list of lists, I'll just show you what the list looks like if the generator object was printed:
In [1]: ll = [(('color'), ('blue')), (('food'), ('grapes')), (('color'), ('blue'))]
# create generator object 'test2'
In [2]: genobj = (each for each in ll)
# create a generator object with counted items
In [3]: count = (test2.count((i), i) for i in test2)
# list count
In [4]: list(count)
This creates the error:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-72-83b1c94e3edd> in <module>()
----> 1 list(count)
<ipython-input-70-829ea68a1314> in <genexpr>(.0)
----> 1 count = (test2.count((i), i) for i in test2)
AttributeError: 'generator' object has no attribute 'count'
So I am stuck here. If I can resolve this, I can move onto getting a frequency count (in the form of a generator object) which would look something like:
[(2, ('color', 'blue')), (1, ('food', 'grapes')), (2, ('color', 'blue'))]
Then I would only want save items with values greater than 2, for visual analysis.

how to solve this error with lambda and sorted method when i try to make sentiment analysis (POS or NEG text)?

Input code:
best = sorted(word_scores.items(), key=lambda w, s: s, reverse=True)[:10000]
Result:
Traceback (most recent call last):
File "C:\Users\Sarah\Desktop\python\test.py", line 78, in <module>
best = sorted(word_scores.items(), key=lambda w, s: s, reverse=True)[:10000]
TypeError: <lambda>() missing 1 required positional argument: 's'
How do I solve it?
If I've understood the format of your word_scores dictionary correctly (that the keys are words and the values are integers representing scores), and you're simply looking to get an ordered list of words with the highest scores, it's as simple as this:
best = sorted(word_scores, key=word_scores.get, reverse=True)[:10000]
If you want to use a lambda to get an ordered list of tuples, where each tuple is a word and a score, and they are ordered by score, you can do the following:
best = sorted(word_scores.items(), key=lambda x: x[1], reverse=True)[:10000]
The difference between this and your original attempt is that I have passed one argument (x) to the lambda, and x is a tuple of length 2 - x[0] is the word and x[1] is the score. Since we want to sort by score, we use x[1].

StopIteration in generators

I'm learning python's generators, iterators, iterables, and I can't explain why the following is not working. I want to create, as an exercise, a simple version of the function zip. Here's what i did:
def myzip(*collections):
iterables = tuple(iter(collection) for collection in collections)
yield tuple(next(iterable) for iterable in iterables)
test = myzip([1,2,3],(4,5,6),{7,8,9})
print(next(test))
print(next(test))
print(next(test))
What I do is:
I have collections which is a tuple of some collections
I create a new tuple iterables where, for each collection (which is iterable), I get the iterator using iter
Then, I create a new tuple where, on each iterable, I call next. This tuple is then yield.
So I expect that at the first execution the object iterables is created (and stored). Then in each iteration (including the first one) I call next on every iterable stored before and return it.
However this is what I get:
(1, 4, 8)
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-108-424963a58e58> in <module>()
8
9 print(next(test))
---> 10 print(next(test))
StopIteration:
So I see that the first iteration is fine and the result is correct. However, the second iteration raise a StopIteration exception and I don't understand why: each iterable still has some values, so none of the nexts return StopIteration. In fact, this works:
def myziptest(*collections):
iterables = tuple(iter(collection) for collection in collections)
for _ in range(3):
print(tuple(next(iterable) for iterable in iterables))
test = myziptest([1,2,3],(4,5,6),{7,8,9})
Output:
(1, 4, 8)
(2, 5, 9)
(3, 6, 7)
So what is going on?
Thanks a lot
Here's a working solution
def myzip(*collections):
iterables = tuple(iter(collection) for collection in collections)
while True:
try:
yield tuple([next(iterable) for iterable in iterables])
except StopIteration:
# one of the iterables has no more left.
break
test = myzip([1,2,3],(4,5,6),{7,8,9})
print(next(test))
print(next(test))
print(next(test))
The difference between this code and yours is that your code only yields one result. Meaning, calling next more than once will give you a StopIteration.
Think of yield x as putting x into a queue, and next as popping from that queue. And when you try to pop from an empty queue, you get the Stopiteration. You can pop only as many as you put.

Difference between map and list iterators in python3

I ran into unexpected behaviour when working with map and list iterators in python3. In this MWE I first generate a map of maps. Then, I want the first element of each map in one list, and the remaining parts in the original map:
# s will be be a map of maps
s=[[1,2,3],[4,5,6]]
s=map(lambda l: map(lambda t:t,l),s)
# uncomment to obtain desired output
# s = list(s) # s is now a list of maps
s1 = map(next,s)
print(list(s1))
print(list(map(list,s)))
Running the MWE as is in python 3.4.2 yields the expected output for s1:
s1 = ([1,4]),
but the empty list [] for s. Uncommenting the marked line yields the correct output, s1 as above, but with the expected output for s as well:
s=[[2,3],[5,6]].
The docs say that map expects an iterable. To this day, I saw no difference between map and list iterators. Could someone explain this behaviour?
PS: Curiously enough, if I uncomment the first print statement, the initial state of s is printed. So it could also be that this behaviour has something to do with a kind of lazy(?) evaluation of maps?
A map() is an iterator; you can only iterate over it once. You could get individual elements with next() for example, but once you run out of items you cannot get any more values.
I've given your objects a few easier-to-remember names:
>>> s = [[1, 2, 3], [4, 5, 6]]
>>> map_of_maps = map(lambda l: map(lambda t: t, l), s)
>>> first_elements = map(next, map_of_maps)
Iterating over first_elements here will in turn iterate over map_of_maps. You can only do so once, so once we run out of elements any further iteration will fail:
>>> next(first_elements)
1
>>> next(first_elements)
4
>>> next(first_elements)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
list() does exactly the same thing; it takes an iterable argument, and will iterate over that object to create a new list object from the results. But if you give it a map() that is already exhausted, there is nothing to copy into the new list anymore. As such, you get an empty result:
>>> list(first_elements)
[]
You need to recreate the map() from scratch:
>>> map_of_maps = map(lambda l: map(lambda t: t, l), s)
>>> first_elements = map(next, map_of_maps)
>>> list(first_elements)
[1, 4]
>>> list(first_elements)
[]
Note that a second list() call on the map() object resulted in an empty list object, once again.

Resources