Home > Mobile >  How can I fix the list index out of range problem?
How can I fix the list index out of range problem?

Time:05-12

So I wanna fill NaN value of the pay date with the date one month after the join date.

Join date Payday1
Okt'10 NaN
Des'10 NaN

My expectation output is:

Join date Payday1
Okt'10 Nov'10
Des'10 Jan'11

I try this code:

months = ["Jan", "Feb", "Mar", "Apr","Mei","Jun","Jul","Agt","Sep","Okt","Nov","Des"]
dateIn="Okt'10" 

def fill_date():  
  dateIn=dateIn.split("'")
  month, year= dateIn[0], int(dateIn[1])

  if month == months[len(months)-1]: 
    year =1 
    month=months[0] 
  else:
    for m in months:
        if m == month:
          month=months[months.index(month) 1] 
  dateOut=f"{month} {year}" 

df['Payday1'] = df['Payday1'].apply(fill_date)

This code is error in this code month=months[months.index(month) 1], it said list index out of range. So how to fix this code ?

CodePudding user response:

Try:

def fill_date(dt):
    mapper = {m: i 1 for i, m in enumerate(months)}
    month, year = dt.split("'")
    
    if mapper[month]==12:
        return f"Jan'{int(year) 1}"
    else:
        return f"{months[mapper[month]]}'{year}"
    
df["Payday1"] = df["Join date"].apply(fill_date)
Input df:
df = pd.DataFrame({"Join date": ["Okt'10", "Des'10"]})

CodePudding user response:

If you want to constrain the index between 0 and len(months), you can use the modulo operator %.

month=months[(months.index(month)   1) % len(months)]

So you would get the following:

def fill_date(dateIn):
    dateIn = dateIn.split("'")
    month, year =  dateIn[0], int(dateIn[1])

    year  = 1 if month == months[-1] else 0

    month = months[(months.index(month)   1) % len(months)]
          
    dateOut = f"{month}'{year}"
  
    return dateOut

CodePudding user response:

I see two methods:

First: add second Jan at the end of list months and this may work.

Second: use break inside for-loop to exit it when you find first matching element.

All problem is because inside if m == month you assign new value to month and in next loops the same line if m == month compares with different value in month and it may compare with Des and tor to get elemenet after Des. But if you use break then it will exit afer finding first matching value (and it will not check if m == month for new value).


Full working code with other changes - ie. you fogot return dateOut in your code.

months = ["Jan", "Feb", "Mar", "Apr","Mei","Jun","Jul","Agt","Sep","Okt","Nov","Des"]

dateIn = "Okt'10" 

import pandas as pd

df = pd.DataFrame({
    'Join date': ["Okt'10", "Des'10"],
    'Payday1': ["NaN", "NaN"],
})
                  
def fill_date(dateIn):
  print(dateIn)
  
  dateIn = dateIn.split("'")
  month, year = dateIn[0], int(dateIn[1])

  if month == months[-1]: 
     year  = 1 
     month = months[0] 
  else:
     for m in months:
        if m == month:
           month = months[months.index(month) 1]
           break  # <--- HERE
          
  dateOut = f"{month}'{year}"
  
  return dateOut
  

df['Payday1'] = df['Join date'].apply(fill_date)

print(df)

Result:

  Join date Payday1
0    Okt'10  Nov'10
1    Des'10  Jan'11

Probably problem could resolve also for m in months[:-1]: to skip Des from list.

  • Related