У меня есть фрейм данных pandas, который выглядит так...
Что мне нужно сделать, так это условно присвоить значения 'my_column' в зависимости от индекса. Первые три строки должны иметь значения «собака», «кошка», «птица». Затем в следующих трех рядах также должны быть слова «собака», «кошка», «птица». Этот шаблон должен применяться до конца набора данных.
Я пробовал следующий код безрезультатно.
for index, row in df.iterrows():
counter=3
my_column='dog'
if counter>3
break
else
counter+=1
my_column='cat'
counter+=1
if counter>3
break
else
counter+=1
my_column='bird'
if counter>3
break
Несколько проблем:
break
выходите из своего цикла, прерывая его досрочно вместо использования структуры if
, elif
, else
См. этот вопрос о том, почему вы не должны обновляться во время итерации.
Вместо этого вы могли бы сделать
values = ["dog", "cat", "bird"]
num_values = len(values)
for index in df.index():
df.at[index, "my_column"] = values[index % num_values]
Я попробовал это решение, но получил следующую ошибку: объект «Int64Index» не может быть вызван. Я запускаю ваш код внутри функции.
Одним из решений было бы превратить собаку-кошку-птицу в pd.Series
и использовать расширенную индексацию:
dcb = pd.Series(["dog", "cat", "bird"])
df["my_column"] = dcb[df.index % len(dcb)].reset_index(drop=True)
Это работает, сначала создав массив индексов из df.index % len(dcb)
:
In [8]: df.index % len(dcb)
Out[8]: Int64Index([0, 1, 2, 0, 1, 2, 0], dtype='int64')
Затем, используя расширенную индексацию, вы можете выбрать элементы из dcb
с помощью этого массива индексов:
In [9]: dcb[df.index % len(dcb)]
Out[9]:
0 dog
1 cat
2 bird
0 dog
1 cat
2 bird
0 dog
dtype: object
Наконец, обратите внимание, что индекс массива выше повторяется. Сбросьте его и удалите старый индекс с помощью .reset_index(drop=True)
и, наконец, назначьте его вашему фрейму данных.
Вот альтернативное решение, использующее бесконечный генератор собаки-кошки-птицы:
In [2]: df
Out[2]:
my_column
0
1
2
3
4
5
6
In [3]: def dog_cat_bird():
...: while True:
...: yield from ("dog", "cat", "bird")
...:
In [4]: dcb = dog_cat_bird()
In [5]: df["my_column"].apply(lambda _: next(dcb))
Out[5]:
0 dog
1 cat
2 bird
3 dog
4 cat
5 bird
6 dog
Name: my_column, dtype: object
Я пробовал оба метода, но в результате присваивание новых значений по какой-то причине пропускало строку.
Похоже, вы что-то неправильно скопировали. Без обид, но приведенный выше код является доказательством того, что решение делает именно то, о чем вы просили, а это означает, что в вашем конкретном фрейме данных есть что-то, что не соответствует вопросу. Не совсем понятно, что вы подразумеваете под "пропущенной строкой".
Создайте словарь:
pet_dict = {0:'dog',
1:'cat',
2:'bird'}
Вы можете получить значение индекса, используя функцию .name и модуль (%) на 3, чтобы получить желаемый результат:
df.apply (lambda x: pet_dict[x.name%3],axis=1)
0 dog
1 cat
2 bird
3 dog
4 cat
5 bird
6 dog
7 cat
8 bird
9 dog
Спасибо. Я смог получить результат, который мне нужен с этим решением!
Как упоминалось в других ответах, ваш код содержит множество логических и синтаксических ошибок. Ключевое слово
break
используется для выхода из цикла. Вы никогда не сможете вернуться в цикл после выхода из него, поэтому, если вы хотите повторить элементы итерации, вам нужно оставаться в цикле, но найти способ сбросить свой счетчик. Этого проще всего добиться с помощью оператора по модулю:%
. Это действительно изящный оператор с массой захватывающих математических свойств, известных под общим названием модульной арифметики.