From: John Posner on
On 3/8/2010 9:39 PM, John Posner wrote:

<snip>

> # gather data
> tally_dict = defaultdict(Tally)
> for i in range(len(x)):
> obj = tally_dict[y[i]]
> obj.id = y[i] <--- statement redundant, remove it
> obj.total += x[i]
> obj.count += 1

-John


From: John Posner on
On 3/8/2010 9:43 PM, John Posner wrote:
> On 3/8/2010 9:39 PM, John Posner wrote:
>
> <snip>

>> obj.id = y[i] <--- statement redundant, remove it

Sorry for the thrashing! It's more correct to say that the Tally class
doesn't require an "id" attribute at all. So the code becomes:

#---------
from collections import defaultdict

class Tally:
def __init__(self):
self.total = 0
self.count = 0

x = [1 ,2, 8, 5, 0, 7]
y = ['a', 'a', 'b', 'c', 'c', 'c']

# gather data
tally_dict = defaultdict(Tally)
for i in range(len(x)):
obj = tally_dict[y[i]]
obj.total += x[i]
obj.count += 1

# process data
result_list = []
for key in sorted(tally_dict):
obj = tally_dict[key]
mean = 1.0 * obj.total / obj.count
result_list.extend([mean] * obj.count)
print result_list
#---------

-John
From: Michael Rudolf on
Am 08.03.2010 23:34, schrieb dimitri pater - serpia:
> Hi,
>
> I have two related lists:
> x = [1 ,2, 8, 5, 0, 7]
> y = ['a', 'a', 'b', 'c', 'c', 'c' ]
>
> what I need is a list representing the mean value of 'a', 'b' and 'c'
> while maintaining the number of items (len):
> w = [1.5, 1.5, 8, 4, 4, 4]

This kinda looks like you used the wrong data structure.
Maybe you should have used a dict, like:
{'a': [1, 2], 'c': [5, 0, 7], 'b': [8]} ?

> I have looked at iter(tools) and next(), but that did not help me. I'm
> a bit stuck here, so your help is appreciated!

As said, I'd have used a dict in the first place, so lets transform this
straight forward into one:

x = [1 ,2, 8, 5, 0, 7]
y = ['a', 'a', 'b', 'c', 'c', 'c' ]

# initialize dict
d={}
for idx in set(y):
d[idx]=[]

#collect values
for i, idx in enumerate(y):
d[idx].append(x[i])

print("d is now a dict of lists: %s" % d)

#calculate average
for key, values in d.items():
d[key]=sum(values)/len(values)

print("d is now a dict of averages: %s" % d)

# build the final list
w = [ d[key] for key in y ]

print("w is now the list of averages, corresponding with y:\n \
\n x: %s \n y: %s \n w: %s \n" % (x, y, w))


Output is:
d is now a dict of lists: {'a': [1, 2], 'c': [5, 0, 7], 'b': [8]}
d is now a dict of averages: {'a': 1.5, 'c': 4.0, 'b': 8.0}
w is now the list of averages, corresponding with y:

x: [1, 2, 8, 5, 0, 7]
y: ['a', 'a', 'b', 'c', 'c', 'c']
w: [1.5, 1.5, 8.0, 4.0, 4.0, 4.0]

Could have used a defaultdict to avoid dict initialisation, though.
Or write a custom class:

x = [1 ,2, 8, 5, 0, 7]
y = ['a', 'a', 'b', 'c', 'c', 'c' ]

class A:
def __init__(self):
self.store={}
def add(self, key, number):
if key in self.store:
self.store[key].append(number)
else:
self.store[key] = [number]
a=A()

# collect data
for idx, val in zip(y,x):
a.add(idx, val)

# build the final list:
w = [ sum(a.store[key])/len(a.store[key]) for key in y ]

print("w is now the list of averages, corresponding with y:\n \
\n x: %s \n y: %s \n w: %s \n" % (x, y, w))

Produces same output, of course.

Note that those solutions are both not very efficient, but who cares ;)

> thanks!

No Problem,

Michael
From: Steve Howell on
On Mar 8, 6:39 pm, John Posner <jjpos...(a)optimum.net> wrote:
> On 3/8/2010 5:34 PM, dimitri pater - serpia wrote:
>
> > Hi,
>
> > I have two related lists:
> > x = [1 ,2, 8, 5, 0, 7]
> > y = ['a', 'a', 'b', 'c', 'c', 'c' ]
>
> > what I need is a list representing the mean value of 'a', 'b' and 'c'
> > while maintaining the number of items (len):
> > w = [1.5, 1.5, 8, 4, 4, 4]
>
> > I have looked at iter(tools) and next(), but that did not help me. I'm
> > a bit stuck here, so your help is appreciated!
>
> Nobody expects object-orientation (or the Spanish Inquisition):
>

Heh. Yep, I avoided OO for this. Seems like a functional problem.
My solution is functional on the outside, imperative on the inside.
You could add recursion here, but I don't think it would be as
straightforward.

def num_dups_at_head(lst):
assert len(lst) > 0
val = lst[0]
i = 1
while i < len(lst) and lst[i] == val:
i += 1
return i

def smooth(x, y):
result = []
while x:
cnt = num_dups_at_head(y)
avg = sum(x[:cnt]) * 1.0 / cnt
result += [avg] * cnt
x = x[cnt:]
y = y[cnt:]
return result


> #-------------------------
> from collections import defaultdict
>
> class Tally:
>      def __init__(self, id=None):
>          self.id = id
>          self.total = 0
>          self.count = 0
>
> x = [1 ,2, 8, 5, 0, 7]
> y = ['a', 'a', 'b', 'c', 'c', 'c']
>
> # gather data
> tally_dict = defaultdict(Tally)
> for i in range(len(x)):
>      obj = tally_dict[y[i]]
>      obj.id = y[i]
>      obj.total += x[i]
>      obj.count += 1
>
> # process data
> result_list = []
> for key in sorted(tally_dict):
>      obj = tally_dict[key]
>      mean = 1.0 * obj.total / obj.count
>      result_list.extend([mean] * obj.count)
> print result_list
> #-------------------------
From: Steve Howell on
On Mar 8, 2:34 pm, dimitri pater - serpia <dimitri.pa...(a)gmail.com>
wrote:
> Hi,
>
> I have two related lists:
> x = [1 ,2, 8, 5, 0, 7]
> y = ['a', 'a', 'b', 'c', 'c', 'c' ]
>
> what I need is a list representing the mean value of 'a', 'b' and 'c'
> while maintaining the number of items (len):
> w = [1.5, 1.5, 8, 4, 4, 4]
>

What results are you expecting if you have multiple runs of 'a' in a
longer list?