Измените pandas фрейм данных в цикле iterrows - PullRequest
2 голосов
/ 09 мая 2020

Я новичок в Python.

Я пытаюсь добавить префикс (серийный номер) к элементу во фрейме данных, используя для l oop, для очистки / подготовки данных перед анализ.

Код

a=pd.read_excel('C:/Users/HP/Desktop/WFH/PowerBI/CMM data.xlsx','CMM_unclean')
a['Serial Number'] = a['Serial Number'].apply(str)
print(a.iloc[72,1])

for index,row in a.iterrows():
    if len(row['Serial Number']) == 6:
        row['Serial Number'] = 'SR0' + row['Serial Number']
        print(row['Serial Number'])

print(a.iloc[72,1])

Результат:

C:\Users\HP\anaconda3\envs\test\python.exe C:/Users/HP/PycharmProjects/test/first.py
101306
SR0101306
101306

Я не понимаю, почему это происходит внутри for l oop, value меняется, но снаружи то же самое.

Ответы [ 3 ]

1 голос
/ 09 мая 2020

Это никогда не изменит фактический фрейм данных с именем a.

TL; DR: строки, которые вы получаете от iterrows, являются копиями, которые больше не связаны с исходным фреймом данных , поэтому правки не изменяют ваш фрейм данных. Однако вы можете использовать индекс для доступа и редактирования соответствующей строки фрейма данных.


ОБЪЯСНЕНИЕ

Почему?

Строки вы возвращаетесь из iterrows - это копии , которые не длиннее , связанных с исходным фреймом данных , поэтому изменения не меняются ваш фреймворк. Однако вы можете использовать index для доступа и редактирования соответствующей строки фрейма данных.


Решение таково:

import pandas as pd

a = pd.read_excel("Book1.xlsx")
a['Serial Number'] = a['Serial Number'].apply(str)

a.head()
#    ID    Serial Number
# 0   1     SR0101306
# 1   2       1101306

print(a.iloc[0,1])
#101306

for index,row in a.iterrows():
    row = row.copy()
    if len(row['Serial Number']) == 6:
        # use the index and .loc method to alter the dataframe
        a.loc[index, 'Serial Number'] = 'SR0' + row['Serial Number']

print(a.iloc[0,1])
#SR0101306
1 голос
/ 09 мая 2020

В документации я читал (курсив оттуда)

никогда не изменяйте то, что вы повторяете. Это не гарантируется во всех случаях. В зависимости от типов данных итератор возвращает копию, а не представление, и запись в него не будет иметь никакого эффекта.

Возможно, это означает, что в вашем случае создается копия, а ссылка не используется. Таким образом, изменение временно применяется к копии, но не к данным во фрейме данных.

0 голосов
/ 09 мая 2020

Поскольку вы уже используете apply, вы можете сделать это прямо внутри функции, которую вы вызываете apply с помощью:

def fix_serial(n):
    n_s = str(n)

    if len(n_s) == 6:
        n_s = 'SR' + n_s

    return n_s

a['Serial Number'] = a['Serial Number'].apply(fix_serial)
...