IndexError: позиционные индексаторы выходят за пределы при работе с DataFrame, где были удалены строки - PullRequest
0 голосов
/ 04 октября 2019

Я получаю ошибку IndexError: positional indexers are out-of-bounds при запуске следующего кода в DataFrame, где строки были отброшены, но не в совершенно новом DataFrame:

Я использую следующие методыдля очистки данных:

import pandas as pd

def get_list_of_corresponding_projects(row: pd.Series, df: pd.DataFrame) -> list:
    """Returns a list of indexes indicating the 'other' (not the current one) records that are for the same year, topic and being a project.
    """
    current_index = row.name
    current_year = row['year']
    current_topic = row['topic']

    if row['Teaching Type'] == "Class":
        mask = (df.index != current_index) & (df['year'] == current_year) & (df['topic'] == current_topic) & (df['Teaching Type'] == "Project")
        return df[mask].index.values.tolist()
    else:
        return list()


def fix_classes_with_corresponding_projects(df: pd.DataFrame) -> pd.DataFrame:
    """Change the Teaching Type of projects having a corresponding class from 'Project' to 'Practical Work'
    """

    # find the projects corresponding to that class
    df['matching_lines'] = df.apply(lambda row: get_list_of_corresponding_projects(row, df), axis=1)

    # Turn the series of lists into a single list without duplicates
    indexes_to_fix = list(set(sum(df['matching_lines'].values.tolist(), [])))

    # Update the records
    df.iloc[indexes_to_fix, df.columns.get_loc('Teaching Type')] = "Practical Work"

    # Remove the column that was used for tagging
    df.drop(['matching_lines'], axis=1, inplace=True)

    # return the data
    return df

Эти методы прекрасно работают при запуске на совершенно новом DataFrame:

df = pd.DataFrame({'year': ['2015','2015','2015','2016','2016','2017','2017','2017','2017'],
                   'Teaching Type':['Class', 'Project', 'Class', 'Class', 'Project', 'Class', 'Class', 'Class', 'Project' ],
                   'topic': ['a', 'a', 'b', 'a', 'c','a','b','a','a']})
display(df)

df = fix_classes_with_corresponding_projects(df)
display(df)

Теперь, если некоторые строки DataFrame получатудаляется (я считаю, что индекс становится непостоянным ), затем код дует:

df = pd.DataFrame({'year': ['2015','2015','2015','2016','2016','2017','2017','2017','2017'],
                   'Teaching Type':['Class', 'Project', 'Class', 'Class', 'Project', 'Class', 'Class', 'Class', 'Project' ],
                   'topic': ['a', 'a', 'b', 'a', 'c','a','b','a','a']})

# Do some 'other' work on the DataFrame
df.drop(2, axis=0, inplace=True)

df = fix_classes_with_corresponding_projects(df)

В приведенном выше примере дается следующая строка:

df.iloc[indexes_to_fix, df.columns.get_loc('Teaching Type')] = "Practical Work"

Чего мне здесь не хватает? Я думал, что, работая со значениями индекса, я был в безопасности от ошибок такого типа.

1 Ответ

1 голос
/ 04 октября 2019

У вас есть логический недостаток в функции fix_classes_with_corresponding_projects: indexes_to_fix содержит индекс значения (не позиции индекса) строк, которые нужно исправить. Затем вы выбираете с помощью iloc, который выбирает строки по позиции. Вам нужно

# Update the records
df.loc[indexes_to_fix, 'Teaching Type'] = "Practical Work"

вместо

df.iloc[indexes_to_fix, df.columns.get_loc('Teaching Type')] = "Practical Work"

Таким образом, ваш оригинальный код работал только по стечению обстоятельств. Если бы у вас был нечисловой индекс (например, создание образца кадра данных с index=list('abcdefghi')), недостаток стал бы сразу очевидным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...