I ran into an error using Python's List comprehension today that I was not expecting. I checked this post:
TypeError: 'int' object is not iterable, why it's happening
which simply explains basically what the error is. My question is a bit more specific though. Why does the 'np.percentile' functions work, but not 'max' and 'min' NOTE: binnedMetric is a dictionary of nested lists, i.e., binnedMetric['key'][num1-numBins][listContainingItemsWithinBin]. I am taking statistics on all the items in each bin. Here is the snippit from my code that works:
tempAvgMetric = [[] for dmx in range(numBins)]
for idx in range(len(binnedMetric[expDir])):
for xxx in range(numBins):
tempAvgMetric[xxx].extend(binnedMetric[expDir][idx][nameNum][xxx])
for idx in range(numBins):
if np.isnan(avgMetric[idx]):
tempAvgMetric[idx] = 0
percentile50 = np.array([np.percentile(tempAvgMetric[dmx], 50) for dmx in range(numBins) if tempAvgMetric])
percentile75 = np.array([np.percentile(tempAvgMetric[dmx], 75) for dmx in range(numBins) if tempAvgMetric])
percentile25 = np.array([np.percentile(tempAvgMetric[dmx], 25) for dmx in range(numBins) if tempAvgMetric])
maximum = np.array([np.amax(tempAvgMetric[dmx]) for dmx in range(numBins) if tempAvgMetric])
minimum = np.array([np.amin(tempAvgMetric[dmx]) for dmx in range(numBins) if tempAvgMetric])
Converting 'nan' to zeros appears to be necessary to get the percentile function to work properly. I also tried using Python's 'min' and 'max' functions as follows:
maximum = np.array([max(tempAvgMetric[dmx]) for dmx in range(numBins) if tempAvgMetric])
minimum = np.array([min(tempAvgMetric[dmx]) for dmx in range(numBins) if tempAvgMetric])
I find it peculiar because I am not iterating over the min function, I am iterating over 'dmx', which is defined as an iterable in the list comprehension. I wouldn't think that the function call would affect anything. As shown above in the "np.percentile" list comprehensions, the loop is almost identical. Any clues as to why this behavior exists would be greatly appreciated. Thank you!
**UPDATE: Here is a functioning code. It works, with no "int object is not iterable" error.
import numpy as np
a = [[1,2,3],[1],[], [4,7,6,8,10],[13,12,0.2]]
b = [[1,4,2],[1,6,7],[6,5,3],[1,4,3],[13,11,1]]
c = [[1,2,3], [1,4,6], [1,4,6], [1], []]
d = [[2],[4],[6],[8],[10]]
binnedMetric = {'tempKey': [[a,b], [c,d]]}
expDir = 'tempKey'
numBins = 5
nameNum = 0
tempAvgMetric = [[] for dmx in range(numBins)]
for idx in range(len(binnedMetric[expDir])):
for xxx in range(numBins):
tempAvgMetric[xxx].extend(binnedMetric[expDir][idx][nameNum][xxx])
avgMetric = np.array([np.mean(tempAvgMetric[dmx]) for dmx in range(numBins) if tempAvgMetric])
varMetric = np.array([np.sqrt(np.var(tempAvgMetric[dmx])) for dmx in range(numBins) if tempAvgMetric])
for idx in range(numBins):
if np.isnan(avgMetric[idx]):
tempAvgMetric[idx] = 0
percentile50 = np.array([np.percentile(tempAvgMetric[dmx], 50) for dmx in range(numBins) if tempAvgMetric])
percentile75 = np.array([np.percentile(tempAvgMetric[dmx], 75) for dmx in range(numBins) if tempAvgMetric])
percentile25 = np.array([np.percentile(tempAvgMetric[dmx], 25) for dmx in range(numBins) if tempAvgMetric])
maximum = np.array([np.amax(tempAvgMetric[dmx]) for dmx in range(numBins) if tempAvgMetric])
minimum = np.array([np.amin(tempAvgMetric[dmx]) for dmx in range(numBins) if tempAvgMetric])
maximum2 = np.array([max(tempAvgMetric[dmx]) for dmx in range(numBins) if tempAvgMetric])
minimum2 = np.array([min(tempAvgMetric[dmx]) for dmx in range(numBins) if tempAvgMetric])
print(percentile50)
print(maximum)
print(maximum2)
simply changing the values of 'a' to
a = [[np.nan, np.nan],[1],[], [4,7,6,8,10],[13,12,0.2]]
breaks the code, but only for 'maximum2', giving the same error that I was running into.