Python Pandas: Create Groups by Range using map - python-2.7

I have a large data set where I am looking to create groups based upon cumulative sum percent of the total. I have gotten this to work by using the map function see below code. Is there a better way to do this say if I wanted to make my groups even more granular? So for example now am looking at 5% increments...what if want to look at 1 % increments. Wondering if there is another way where I don't have to explicitly enter them into my "codethem" function.
def codethem(dl):
if dl < .05 : return '5'
elif .05 < dl <= .1: return '10'
elif .1 < dl <= .15: return '15'
elif .15 < dl <= .2: return '20'
elif .2 < dl <= .25: return '25'
elif .25 < dl <= .3: return '30'
elif .3 < dl <= .35: return '35'
elif .35 < dl <= .4: return '40'
elif .4 < dl <= .45: return '45'
elif .45 < dl <= .5: return '50'
elif .5 < dl <= .55: return '55'
elif .55 < dl <= .6: return '60'
elif .6 < dl <= .65: return '65'
elif .65 < dl <= .7: return '70'
elif .7 < dl <= .75: return '75'
elif .75 < dl <= .8: return '80'
elif .8 < dl <= .85: return '85'
elif .85 < dl <= .9: return '90'
elif .9 < dl <= .95: return '95'
elif .95 < dl <= 1: return '100'
else: return 'None'
my_df['code'] = my_df['sales_csum_aspercent'].map(code them)
Thank you!

there is a special method for that - pd.cut()
Demo:
create random DF:
In [393]: df = pd.DataFrame({'a': np.random.rand(10)})
In [394]: df
Out[394]:
a
0 0.860256
1 0.399267
2 0.209185
3 0.773647
4 0.294845
5 0.883161
6 0.985758
7 0.559730
8 0.723033
9 0.126226
we should specify bins when calling pd.cut():
In [404]: np.linspace(0, 1, 11)
Out[404]: array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
In [395]: pd.cut(df.a, bins=np.linspace(0, 1, 11))
Out[395]:
0 (0.8, 0.9]
1 (0.3, 0.4]
2 (0.2, 0.3]
3 (0.7, 0.8]
4 (0.2, 0.3]
5 (0.8, 0.9]
6 (0.9, 1]
7 (0.5, 0.6]
8 (0.7, 0.8]
9 (0.1, 0.2]
Name: a, dtype: category
Categories (10, object): [(0, 0.1] < (0.1, 0.2] < (0.2, 0.3] < (0.3, 0.4] ... (0.6, 0.7] < (0.7, 0.8] < (0.8, 0.9] < (0.9, 1]]
if we want to have a custom labels, we should explicitly specify them:
In [401]: bins = np.linspace(0,1, 11)
NOTE: bin labels must be one fewer than the number of bin edges
In [402]: labels = (bins[1:]*100).astype(int)
In [412]: labels
Out[412]: array([ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100])
In [403]: pd.cut(df.a, bins=bins, labels=labels)
Out[403]:
0 90
1 40
2 30
3 80
4 30
5 90
6 100
7 60
8 80
9 20
Name: a, dtype: category
Categories (10, int64): [10 < 20 < 30 < 40 ... 70 < 80 < 90 < 100]
Lets do it with the 5% step
In [419]: bins = np.linspace(0, 1, 21)
In [420]: bins
Out[420]: array([ 0. , 0.05, 0.1 , 0.15, 0.2 , 0.25, 0.3 , 0.35, 0.4 , 0.45, 0.5 , 0.55, 0.6 , 0.65, 0.7 , 0.75, 0.8 , 0.8
5, 0.9 , 0.95, 1. ])
In [421]: labels = (bins[1:]*100).astype(int)
In [422]: labels
Out[422]: array([ 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100])
In [423]: pd.cut(df.a, bins=bins, labels=labels)
Out[423]:
0 90
1 40
2 25
3 80
4 30
5 90
6 100
7 60
8 75
9 15
Name: a, dtype: category
Categories (20, int64): [5 < 10 < 15 < 20 ... 85 < 90 < 95 < 100]

Related

How to set different (if) parameters for the same number in a list?

I don't even know how to format this paragraph right haha
Hi there I'm completely new to Python.
I was wondering if I have a list
how do I take the output of a first if command and use on the next
Example
L= [23, 91, 0, -11, 4, 23, 49]
for i in L:
if(i > 10):
print(i * 30)
example
I also want to check if the output of this number is an even number if so (+6) -- for the output of that
if number is not equal to -11 I want to add 10.
So I got 23 > 10= (23*30 = 690) // 690 is an even number ( 690 + 6=696) // it not equal to -11 so (696+10= 706).
How do I do this for every number on the list? Excuse my lack of knowledge it's literally my first python class and my first exercises.
Is that what you want?
L= [23, 91, 0, -11, 4, 23, 49]
for i in L:
if i > 10:
num = i * 30
if num % 2 == 0:
num += 6
if i != -11:
num += 10
else:
pass
print(num)
output:
706
2746
706
1486

How to generate numbers which is containing only 0's and 9's

Hi I want to generate numbers which is contain only 0's and 9's in python or c++ doesn't matter
I write it like:
for i in range(0,100):
random_number = 9 * 10**i
for j in range(0,i):
second_sum = 9 *10 ** j
random_number += second_sum
print(random_number)
but output like this
9
99
999
9999
99999
999999
9999999
99999999
999999999
9999999999
............
..............
But expected output is
9
90
99
900
909
990
999
9000
9009
9090
9099
9900
9990
9999
--snip--
Anyone help me please :)
Based on #B.Go's comment, here's solution with replacing the ones:
def generate(n=5):
for i in range(1, 2**n):
yield int('{:b}'.format(i).replace('1', '9'))
print([*generate(5)])
Prints:
[9, 90, 99, 900, 909, 990, 999, 9000, 9009, 9090, 9099, 9900, 9909, 9990, 9999, 90000, 90009, 90090, 90099, 90900, 90909, 90990, 90999, 99000, 99009, 99090, 99099, 99900, 99909, 99990, 99999]
(EDITED)
Your approach would not work because:
you are not printing random_number just often enough.
even if you were, you are not producing all the possible permutations with repetitions.
for i in range(0, 3):
random_number = 9 * 10 ** i
print(random_number) # <--- HERE
for j in range(0, i):
second_sum = 9 * 10 ** j
random_number += second_sum
print(random_number) # <--- HERE
# 9
# 90
# 99
# 900
# 909
# 999
990 is missing and this approach is not easy to generalize, as it would need an arbitrary number of nested loops.
There are several other possible approaches, either based on itertools.product (which is more general and simpler to extend as an infinite generator) or on the observation that a binary representation of the natural numbers is very close to your target output:
import itertools
def my_gen_itertools(max_len=0, items='09'):
length = 1
while max_len and length <= max_len:
for x in itertools.product(items, repeat=length):
if x[0] != items[0]:
yield int(''.join(x))
length += 1
def my_gen_bin_mult(n, factor=9):
for i in range(1, 2 ** n):
yield int(bin(i)[2:]) * factor
def my_gen_bin_replace(n, subst='9'):
for i in range(1, 2 ** n):
yield int('{:b}'.format(i).replace('1', subst))
def my_gen_bit_mult(n, factor=9):
k = [10 ** i for i in range(n)]
for value in range(1, 2 ** n):
result = 0
j = 0
while value:
result += (value & 1) * k[j]
value >>= 1
j += 1
yield result * factor
Note that my_gen_bin_replace() is essentially the solution proposed in #AndrejKesely's answer except that is uses the more efficient bin() call for obtaining the binary representation, and both my_gen_bin_replace() and my_gen_bin_mult() are implement the approach proposed in #Orace's answer.
my_gen_bit_mult() is similar to my_gen_bin_mult() except that this is handled without the intermediate string representation, but uses the rather expensive power computation and Python direct loopings, but it would be the easiest to convert to C++ (where direct looping would not be that slow).
Speed-wise, multiplying the binary representation seems to be the fastest:
funcs = my_gen_itertools, my_gen_bin_mult, my_gen_bin_replace, my_gen_bit_mult
for func in funcs:
print()
print(func.__name__)
print(list(func(4)))
%timeit list(func(20))
# my_gen_itertools
# [9, 90, 99, 900, 909, 990, 999, 9000, 9009, 9090, 9099, 9900, 9909, 9990, 9999]
# 1 loop, best of 3: 839 ms per loop
# my_gen_bin_mult
# [9, 90, 99, 900, 909, 990, 999, 9000, 9009, 9090, 9099, 9900, 9909, 9990, 9999]
# 1 loop, best of 3: 572 ms per loop
# my_gen_bin_replace
# [9, 90, 99, 900, 909, 990, 999, 9000, 9009, 9090, 9099, 9900, 9909, 9990, 9999]
# 1 loop, best of 3: 739 ms per loop
# my_gen_bit_mult
# [9, 90, 99, 900, 909, 990, 999, 9000, 9009, 9090, 9099, 9900, 9909, 9990, 9999]
# 1 loop, best of 3: 3.97 s per loop
You just need one loop, say i in [0..100], convert i to it's binary representation (only 0 and 1), and replace the 1 by 9 (if you have an integer at this point, you can multiply by 9).
Here a method that convert any integer to a string of it's binary representation but with 0&9 instead of 0&1.
n=int(input('please enter the no. in decimal format: '))
x=n
k=[]
while (n>0):
a=int(float(n%2))
k.append(a)
n=(n-a)/2
k.append(0)
string=""
for j in k[::-1]:
string=string+str(j*9)
print('The binary no. for %d is %s'%(x, string))
It is not the best performing version, and it may be refined for your needs, but it can be an idea for a solution.
#!/usr/bin/env python3
def with_digits(n):
assert(n > 0)
if n == 1:
return [0, 9]
prevs = with_digits(n-1)
values = [] + prevs
for prev in prevs:
values.append(9 * 10 ** (n-1) + prev)
return values
if __name__ == '__main__':
print(with_digits(5))

Capture undefined number of items in Regex

I want to capture the following data:
[TREND, JOHN, DATA1, 0.17, 33.34, 26, 33.33, 0.25, 33.33, DATA2, 0.26, 20.0, 261, 20.0, 0.234, 20.0, 0.1, 20.0, 5, 20.0, FINAL, 245]
From the following text:
Market
#TREND
Person: JOHN
DATA1
1) 0.17 (33.34%)
2) 26 (33.33%)
3) 0.25 (33.33%)
* random text here
DATA2
1) 0.26 (20.0%)
2) 261 (20.0%)
3) 0.234 (20.0%)
4) 0.1 (20.0%)
5) 5 (20.0%)
* qsdfdsf random dsfg text random here
FINAL
245
Signature
I have written the following Regex code that works properly in this precise example :
#(TREND)\n+\w*:\s*(JOHN)\n+(DATA1)\n\d\S\s(\d+.?\d*)\s\((\d+.?\d*)%\)\s*\n\d\S\s(\d+.?\d*)\s\((\d+.?\d*)%\)\s*\n\d\S\s(\d+.?\d*)\s\((\d+.?\d*)%\)\s*\n.*\n*(DATA2)\n\d\S\s(\d+.?\d*)\s\((\d+.?\d*)%\)\s*\n\d\S\s(\d+.?\d*)\s\((\d+.?\d*)%\)\s*\n\d\S\s(\d+.?\d*)\s\((\d+.?\d*)%\)\s*\n\d\S\s(\d+.?\d*)\s\((\d+.?\d*)%\)\s*\n\d\S\s(\d+.?\d*)\s\((\d+.?\d*)%\)\s*\n.*\n*(FINAL)\n(\d+)
I would like to make it extentable for random number of item of DATA1 and DATA2 from 1 to 10 items each :
Market
#TREND
Person: JOHN
DATA1
1) 0.17 (33.34%)
2) 26 (33.33%)
3) 0.25 (33.33%)
4) 0.11 (40.40%)
5) 0.222 (50.50%)
* random text here
DATA2
1) 0.26 (20.0%)
2) 261 (20.0%)
3) 0.234 (20.0%)
* qsdfdsf random dsfg text random here
FINAL
245
Signature

Calculating paystring for loan data

Example:
Input: cpi = 100.0, payments = [100.0, 94.0, 90.0, 100.0, 200.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0 ]
Output: paystring = [0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
Explanation: Since the first payment was 100.0 and that is greater than or equal to cpi - 5.0 (95.0) then the first element in the output is 0. Then the next element is 1 since 94.0 is less than cpi - 5.0 (95.0) i.e. missed a payment, then since the next element 90.0 is less than cpi - 5.0 (95.0) i.e. missed another payment than now we are at 2 (or 2 total missed payments). Then in the next element we had 100 then that counts as 1 payment made so now we made that payment that was due but we still didn't cover the other two payments from the prior month so we are still at 2. Then the process continues.
I have this so far:
double cpi = 100.0;
std::vector<double> payments = { 100.0, 94.0, 90.0, 100.0, 200.0, 300.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0 };
std::vector<int> paystring(payments.size(), 0);
int count = 0;
for (int i = 0; i < payments.size(); ++i) {
if (payments[i] <= cpi - 5.0) {
paystring[i] = ++count;
}
else {
paystring[i] = count;
}
}
for (auto it : paystring)
std::cout << it << " ";
Although, this is not correct since it fails to update count when I made lets say the full payment or more than the due amount (cpi). I just want to know what I need to change in my logic to make this work. Let me know if the example provided is unclear.
For example say I have
Input: cpi = 100.0, payments = [100.0, 94.0, 90.0, 100.0, 200.0, 100.0, 300.0, 100.0, 100.0, 100.0, 100.0, 100.0 ]
Output: [0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0]
But I get
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
Here is a few more examples that are correct:
You have a condition that if payment is too low, penalty is added, the customer is one month behind.
Add another condition: If over payment is made, for example $200, you want to give customer credit, that puts the customer one month ahead. Then add a condition that the customer is not ahead by a negative count.
std::vector<double> payments = {
100, 94, 90, 100, 200, 100, 300, 100, 100, 100, 100, 100
//"0 1 1 0 -1 0 -2 0 0 0 0 0 <-penalty
//"0 1 2 2 1 1 0 0 0 0 0 0 <-penalty sum
};
double cpi = 100.0;
for(int i = 0; i < payments.size(); ++i)
{
double payment = payments[i];
if(payment <= (cpi - 5.0))
{
//one month behind on payment
count++;
}
while((payment > cpi) && count)
{
//customer made large payment.
//allow count to decrease.
//but count cannot be less than zero
count--;
payment -= cpi;
}
paystring[i] = count;
}
Ouput for 100, 94, 90, 100, 200, 100, 100, 100, 100, 100, 100, 100:
0 1 2 2 2 2 2 2 2 2 2 2 //expected output
0 1 2 2 1 1 1 1 1 1 1 1 //result
Ouput for 100, 94, 90, 100, 200, 100, 300, 100, 100, 100, 100, 100:
0 1 2 2 1 0 0 0 0 0 0 0 //expected output
0 1 2 2 1 1 0 0 0 0 0 0 //result
My output is not the same, maybe the expected output is incorrect or you left something out. Note the 6th payment is 100, so there shouldn't be any change for that index.

Pygame 2,7 Collision To 3,3

I have recently made a game in python 2.7.6 with pygame and I am now converting all of the syntax and code to work with python 3.3.3. But I am having an issue with collision. Before I converted the collisions worked flawlessly, but in 3.3.3 all the collisions completely messed up. Here is my current code for the player, zombie and boss collisions:
def player_move(self):
# Line start
self.point = self.player.rect.x + 30, self.player.rect.y + 30
# add gravity
self.player.do_jump()
# simulate gravity
self.player.on_ground = False
if not self.player.on_ground and not self.player.jumping:
self.player.velY = 4
if self.player.rect.y >= 680:
self.player.lives -= 1
self.player.rect.x = 320
self.player.rect.y = 320
# Drops
for drop in self.gameDrops:
if pygame.sprite.collide_rect(self.player, drop):
if type(drop) == HealthDrop:
self.player.health += 50
self.gameDrops.remove(drop)
elif type(drop) == SuperHealthDrop:
self.player.health += 1000
self.gameDrops.remove(drop)
elif type(drop) == TriBullets:
self.player.power = POWER_TRIBULLETS
self.gameDrops.remove(drop)
elif type(drop) == ShieldDrop:
self.player.power = POWER_SHIELD
self.gameDrops.remove(drop)
if self.player.score >= self.next_level_score:
self.game_state = STATE_VICTORY
self.player.score = 0
self.zombieskilled = 0
self.alivetime = 0
self.lives = 3
self.health = 200
self.player.rect.x = 320
self.player.rect.y = 320
for zombie in self.zombies:
zombie.rect.x = random.randint(0, 1280)
zombie.rect.y = random.randint(0, 100)
# Health
for m in self.meteors:
if pygame.sprite.collide_rect(self.player, m):
if self.player.power == POWER_SHIELD:
self.player.health -= 25
else:
self.player.health -= 50
for zombie in self.zombies:
if pygame.sprite.collide_rect(self.player, zombie):
if self.player.power == POWER_SHIELD:
self.player.health -= 1
else:
self.player.health -= 5
for boss in self.bosses:
if pygame.sprite.collide_rect(self.player, boss):
if self.player.power == POWER_SHIELD:
self.player.health -= 50
else:
self.player.health -= 50
# check if we die
if self.player.health <= 0:
self.player.power = POWER_NONE
self.player.lives -= 1
self.player.rect.x = 320
self.player.rect.y = 320
self.player.health = 200
if self.player.lives <= 0:
self.player.lives += 3
self.player.score = 0
self.targetscore = 100
self.player.rect.x = 320
self.player.rect.y = 320
self.game_state = STATE_GAMEOVER
for zombie in self.zombies:
zombie.rect.x = random.randint(0, 1280)
zombie.rect.y = random.randint(0, 100)
# move player and check for collision at the same time
self.player.rect.x += self.player.velX
self.check_collision(self.player, self.player.velX, 0)
self.player.rect.y += self.player.velY
self.check_collision(self.player, 0, self.player.velY)
def zombie_move(self, zombie_sprite):
# add gravity
zombie_sprite.do_jump()
percentage = random.randint(0, 100)
# simualte gravity
zombie_sprite.on_ground = False
if not zombie_sprite.on_ground and not zombie_sprite.jumping:
zombie_sprite.velY = 8
if zombie_sprite.jumping:
zombie_sprite.velX = 0
for zombie in self.zombies:
if zombie.rect.y >= 680:
self.zombies.remove(zombie)
dx = zombie_sprite.rect.x - self.player.rect.x
if dx > 20 and not zombie_sprite.jumping:
zombie_sprite.velX = -5
elif dx < 20 and not zombie_sprite.jumping:
zombie_sprite.velX = +5
# Zombie damage
for zombie in self.zombies:
for m in self.meteors:
if pygame.sprite.collide_rect(m, zombie):
zombie.health -= 10
if zombie.health <= 0:
if (percentage >= 0) and (percentage < 40):
self.gameDrops.append(HealthDrop(zombie.rect.x + 10, zombie.rect.y + 30))
elif (percentage >= 0) and (percentage < 5):
self.gameDrops.append(SuperHealthDrop(zombie.rect.x + 20, zombie.rect.y + 30))
elif (percentage >= 1) and (percentage < 20):
self.gameDrops.append(TriBullets(zombie.rect.x + 30, zombie.rect.y + 30, self.player.direction))
elif (percentage >= 1) and (percentage < 50):
self.gameDrops.append(ShieldDrop(zombie.rect.x + 40, zombie.rect.y + 30))
self.zombieskilled += 0
self.player.score += 0
self.meteors.remove(m)
break
for zombie in self.zombies:
for b in self.bullets:
if pygame.sprite.collide_rect(b, zombie):
#The same bullet cannot be used to kill
#multiple zombies and as the bullet was
#no longer in Bullet.List error was raised
zombie.health -= 10
self.bullets.remove(b)
if zombie.health <= 0:
if (percentage >= 0) and (percentage < 40):
self.gameDrops.append(HealthDrop(zombie.rect.x + 10, zombie.rect.y + 30))
elif (percentage >= 0) and (percentage < 5):
self.gameDrops.append(SuperHealthDrop(zombie.rect.x + 20, zombie.rect.y + 30))
elif (percentage >= 1) and (percentage < 20):
self.gameDrops.append(TriBullets(zombie.rect.x + 30, zombie.rect.y + 30, self.player.direction))
elif (percentage >= 1) and (percentage < 50):
self.gameDrops.append(ShieldDrop(zombie.rect.x + 40, zombie.rect.y + 30))
self.zombieskilled += 1
self.player.score += 10
self.total_score += 10
self.zombies.remove(zombie)
break
# move zombie and check for collision
zombie_sprite.rect.x += zombie_sprite.velX
self.check_collision(zombie_sprite, zombie_sprite.velX, 0)
zombie_sprite.rect.y += zombie_sprite.velY
self.check_collision(zombie_sprite, 0, zombie_sprite.velY)
def boss_move(self, boss_sprite):
# add gravity
boss_sprite.do_jump()
percentage = random.randint(0, 100)
# simualte gravity
boss_sprite.on_ground = False
if not boss_sprite.on_ground and not boss_sprite.jumping:
boss_sprite.velY = 8
if boss_sprite.jumping:
boss_sprite.velX = 0
for boss in self.bosses:
if boss.rect.y >= 620:
self.bosses.remove(boss)
dx = boss_sprite.rect.x - self.player.rect.x
if dx > 20 and not boss_sprite.jumping:
boss_sprite.velX = -5
elif dx < 20 and not boss_sprite.jumping:
boss_sprite.velX = +5
# Zombie damage
for boss in self.bosses:
for m in self.meteors:
if pygame.sprite.collide_rect(m, boss):
boss.health -= 0
if boss.health <= 0:
if (percentage >= 0) and (percentage < 40):
self.gameDrops.append(HealthDrop(boss.rect.x + 10, boss.rect.y + 30))
elif (percentage >= 0) and (percentage < 5):
self.gameDrops.append(SuperHealthDrop(boss.rect.x + 20, boss.rect.y + 30))
elif (percentage >= 1) and (percentage < 20):
self.gameDrops.append(TriBullets(boss.rect.x + 30, boss.rect.y + 30, self.player.direction))
elif (percentage >= 1) and (percentage < 50):
self.gameDrops.append(ShieldDrop(boss.rect.x + 40, boss.rect.y + 30))
self.zombieskilled += 0
self.player.score += 0
self.meteors.remove(m)
break
for boss in self.bosses:
for b in self.bullets:
if pygame.sprite.collide_rect(b, boss):
#The same bullet cannot be used to kill
#multiple bosses and as the bullet was
#no longer in Bullet.List error was raised
boss.health -= 5
self.bullets.remove(b)
if boss.health <= 0:
if (percentage >= 0) and (percentage < 50):
self.gameDrops.append(SuperHealthDrop(boss.rect.x + 90, boss.rect.y + 90))
elif (percentage >= 0) and (percentage < 50):
self.gameDrops.append(TriBullets(boss.rect.x + 90, boss.rect.y + 90, self.player.direction))
self.zombieskilled += 1
self.player.score += 50
self.total_score += 50
self.bosses.remove(boss)
break
# move boss and check for collision
boss_sprite.rect.x += boss_sprite.velX
self.check_collision(boss_sprite, boss_sprite.velX, 0)
boss_sprite.rect.y += boss_sprite.velY
self.check_collision(boss_sprite, 0, boss_sprite.velY)
def check_collision(self, sprite, x_vel, y_vel):
# for every tile in Background.levelStructure, check for collision
for block in self.moon.get_surrounding_blocks(sprite):
if block is not None:
if pygame.sprite.collide_rect(sprite, block):
# we've collided! now we must move the collided sprite a step back
if x_vel < 0:
sprite.rect.x = block.rect.x + block.rect.w
if type(sprite) is Zombie:
# the sprite is a zombie, let's make it jump
if not sprite.jumping:
sprite.jumping = True
sprite.on_ground = False
else:
sprite.jumping = False
sprite.on_ground = True
if x_vel > 0:
sprite.rect.x = block.rect.x - sprite.rect.w
if type(sprite) is Zombie:
# the sprite is a zombie, let's make it jump
if not sprite.jumping:
sprite.jumping = True
sprite.on_ground = False
else:
sprite.jumping = False
sprite.on_ground = True
if y_vel < 0:
sprite.rect.y = block.rect.y + block.rect.h
if y_vel > 0 and not sprite.on_ground:
sprite.on_ground = True
sprite.rect.y = block.rect.y - sprite.rect.h
That is all of the code from the player, zombie and boss for them you collide and there functions so they know to collide. I have called the collision function too as you can see in the code for all three. I am really annoyed at this because I am not sure whether it is to do with syntax or what. Any help will be appreciated. Thank you.
I have finally found the fix! In my levelstructure file to randomly generate the terrain and position. In my generation class I had a get_surrounding_blocks as you can see in def check_collision. In that surrounding_blocks I had:
def get_surrounding_blocks(self, sprite):
# calculate the grid position of the sprite
sprite_x = sprite.rect.x / 64
sprite_y = sprite.rect.y / 64
And in python 2.7.6 one division sign (/) will give you an integer but in python 3.3.3 you must do // to get an integer otherwise you may get a float with just one /.