I have this data frame where I sliced columns from the original data frame:
Type 1 Attack
Grass 62
Grass 82
Dragon 100
Fire 52
Rock 100
I want to create each Pokemon’s adjusted attack attribute against grass Pokemon based on ‘Type 1’ where;
- the attack attribute is doubled if grass Pokemon are bad against that type
- halved if they are good against that type
- else remains the same.
I have looping through the data:
grass_attack = []
for value in df_["Type 1"]:
if value ==["Type 1 == Fire"] or value==["Type 1 == Flying"] or value==["Type 1 == Poison"] or value==["Type 1 == Bug"] or value==["Type1== Steel"] or value ==["Type 1 == Grass"] or value ==["Type 1 == Dragon"]:
result.append(df_["Attack"]/2)
elif value==["Type 1==Ground"] or value==["Type1== Ground"] or value==["Type 1 == Water"]:
grass_attack.append(df_["Attack"]*2)
else:
grass_attack.append(df_["Attack"])
df_["grass_attack"] = grass_attack
print(df_)
but I got some crazy results after this. How can I efficiently loop through a data frame's column in order to adjust another column?
or is there another way to do this?
CodePudding user response:
There is some issues with your code as @azro pointed in the comments and there is no need for a loop here. You can simply use numpy.select
to create a multi-conditionnal column.
Here is an example to give you the general logic :
df["Attack"] = df["Attack"].astype(int)
conditions = [df["Type 1"].eq("Grass"), df["Type 1"].isin(["Fire", "Rock"])]
choices = [df["Attack"].div(2), df["Attack"].mul(2)]
df["grass_attack"] = np.select(conditions, choices, default=df["Attack"]).astype(int)
# Output :
print(df)
Type 1 Attack grass_attack
0 Grass 62 31
1 Grass 82 41
2 Dragon 100 100
3 Fire 52 104
4 Rock 100 200
CodePudding user response:
You could use apply
to do the necessary calculations. In the following code, the modify_Attack()
function is used to calculate the Grass Attack
values based on the Type1
and Attack
values.
- Type 1 values that are in the
bad
list will have their attack values halved. - Type 1 values that are in the
good
list will have their attack values doubled. - All other attack values will remain unchanged.
Here is the code:
import pandas as pd
# Create dataframe
df = pd.DataFrame({ 'Type 1': ['Grass', 'Grass', 'Dragon', 'Fire', 'Rock'],
'Attack': [62, 82, 100, 52, 100]})
# Function to modify the Attack value based on the Type 1 value
def modify_Attack(type_val, attack_val):
bad = ['Fire', 'Flying', 'Poison', 'Bug', 'Steel', 'Grass', 'Dragon']
good = ['Ground','Water']
result = attack_val # default value is unchanged
if type_val in bad:
result /= 2
elif type_val in good:
result *= 2
return result
# Create the Grass Attack column
df['Grass Attack'] = df.apply(lambda x: modify_Attack(x['Type 1'], x['Attack']), axis=1).astype(int)
# print the dataframe
print(df)
OUTPUT:
Type 1 Attack Grass Attack
0 Grass 62 31
1 Grass 82 41
2 Dragon 100 50
3 Fire 52 26
4 Rock 100 100