В Python с Pandas у меня есть функция для изменения индекса DataFrame. Но он также изменяет индекс исходного DataFrame - PullRequest
0 голосов
/ 13 июля 2020

У меня есть следующий файл analysis.py. Функция group_analysis изменяет индекс даты и времени df_input столбцом Count df_input

# analysis.py
import pandas as pd

def group_analysis(df_input):
    df_input.index = df_input.index - pd.to_timedelta(df_input.Count, unit = 'days')
    df_ouput = df_input.sort_index()

    return df_ouput

def test(df):
    df = df + 1
    return df

И у меня есть следующий фрейм данных.

x = pd.DataFrame(np.arange(1,14), index = pd.date_range('2020-01-01', periods = 13, freq= 'D'), columns = ['Count'])
            Count
2020-01-01      1
2020-01-02      2
2020-01-03      3
2020-01-04      4
2020-01-05      5
2020-01-06      6
2020-01-07      7
2020-01-08      8
2020-01-09      9
2020-01-10     10
2020-01-11     11
2020-01-12     12
2020-01-13     13

Когда я запускаю следующий код,

import analysis
y = analysis.group_analysis(x)

изменяется индекс даты и времени как для x, так и для y (поэтому x.equals(y) это True). Почему group_analysis меняет как входной, так и выходной индекс datetime? И как я могу заставить его изменить только индекс datetime y (но не x)?

Однако при запуске следующего кода x не изменяется (так, x.equals(y) составляет True)

import analysis
y = analysis.test(x)

EDIT: добавлен анализ.test (df).

Ответы [ 2 ]

1 голос
/ 13 июля 2020

Причина такого поведения в том, что при вызове group_analysis вы не передаете в функцию копию фрейма данных, а, скорее, ссылку на исходные данные в памяти компьютера. Следовательно, если вы измените данные, стоящие за ним, исходные данные (которые являются такими же) также будут изменены.

Для очень хорошего объяснения обратитесь к https://robertheaton.com/2014/02/09/pythons-pass-by-object-reference-as-explained-by-philip-k-dick/.

Для предотвращения этого создайте копию данных при входе в функцию:

...
def group_analysis(df):
    df_input = df.copy()
    ...
0 голосов
/ 13 июля 2020

Когда вы передаете фрейм данных функции, он передает ссылку на фрейм данных. Итак, любое изменение на месте, которое вы делаете с фреймом данных, будет отражаться в переданном фрейме данных.

Но в случае вашей функции test добавление возвращает копию фрейма данных в памяти . Откуда я это знаю? Просто выведите идентификатор ссылки на память переменной до и после операции.

>>> def test(df):
...     print(id(df))
...     df = df + 1
...     print(id(df))
...     return df
... 
>>> test(df)
139994174011920
139993943207568

Заметили изменение? Это означает, что его ссылка была изменена. Следовательно, это не влияет на исходный фрейм данных.

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