Pandas: как использовать приложение для создания нового фрейма данных

Я обнаружил странное поведение в Python Pandas и хотел спросить, виновата ли я в этом или это настоящая ошибка программы. Возьмем следующий DataFrame:

data = DataFrame({'k2':[1, 2, 3, ], 'name':['joe', 'mark', 'carl']})
data.set_index('name', drop=False, inplace=True)

Если я создам функцию, которая возвращает объект серии, подобный этому

def my_test(i, x):
     x['interrel'] = x.apply(lambda row: i['k2'] - row['k2'] if i['name'] != row['name'] else 0, axis=1)
     print x['interrel'] 
     return x['interrel']

и примените эту функцию, используя применить к созданному DataFrame, используя

  data.apply(lambda row: my_test(row, data), axis=1)

все, что я получаю на выходе, - это последняя вычисленная строка, умноженная на три. Однако оператор печати в функции my_test показывает, что вычисления верны. Кажется, что только объекты определенной серии добавлены неправильно.

Можете ли вы восстановить эту проблему? Я что-то не понял относительно использования функции применения?

Учтите, что это всего лишь пример, я не прошу другого способа сделать попарные различия в Pandas.

Любая помощь приветствуется


person Andy    schedule 11.05.2015    source источник
comment
Ну, вы передаете df в качестве второго параметра, поэтому конечный результат будет последней операцией   -  person EdChum    schedule 11.05.2015
comment
Спасибо, вы правы, если я делаю data.copy (), он работает безупречно. Не могли бы вы подробнее рассказать о своем ответе в качестве отдельного ответа, потому что я не понимал, почему эта последняя строка транслируется в каждой строке.   -  person Andy    schedule 11.05.2015


Ответы (1)


Поскольку вы передаете свой data df в качестве ссылки и каждый раз назначаете его напрямую, вызывая apply в своей функции, тогда он перезаписывается последней операцией:

In [20]:

def my_test(i, x):
    x['interrel'] = x.apply(lambda row: i['k2'] - row['k2'] if i['name'] != row['name'] else 0, axis=1)
    #print(x['interrel'])
    print("x-----",x, "\n-------")
    return x['interrel']
data.apply(lambda row: my_test(row, data), axis=1)
x-----       k2  name  interrel
name                    
joe    1   joe         0
mark   2  mark        -1
carl   3  carl        -2 
-------
x-----       k2  name  interrel
name                    
joe    1   joe         0
mark   2  mark        -1
carl   3  carl        -2 
-------
x-----       k2  name  interrel
name                    
joe    1   joe         1
mark   2  mark         0
carl   3  carl        -1 
-------
x-----       k2  name  interrel
name                    
joe    1   joe         2
mark   2  mark         1
carl   3  carl         0 
-------
Out[20]:
name  joe  mark  carl
name                 
joe     2     1     0
mark    2     1     0
carl    2     1     0

Как вы выяснили, если вы передаете копию своих данных, то операции выполняются с копией исходных данных и возвращается правильный результат, вы можете видеть, что data df не изменяется:

 In [22]:

def my_test(i, x):
    x['interrel'] = x.apply(lambda row: i['k2'] - row['k2'] if i['name'] != row['name'] else 0, axis=1)
    #print(x['interrel'])
    print("x-----",x, "\n-------")
    return x['interrel']
print(data.apply(lambda row: my_test(row, data.copy()), axis=1))
print(data)
x-----       k2  name  interrel
name                    
joe    1   joe         0
mark   2  mark        -1
carl   3  carl        -2 
-------
x-----       k2  name  interrel
name                    
joe    1   joe         0
mark   2  mark        -1
carl   3  carl        -2 
-------
x-----       k2  name  interrel
name                    
joe    1   joe         1
mark   2  mark         0
carl   3  carl        -1 
-------
x-----       k2  name  interrel
name                    
joe    1   joe         2
mark   2  mark         1
carl   3  carl         0 
-------
name  joe  mark  carl
name                 
joe     0    -1    -2
mark    1     0    -1
carl    2     1     0
      k2  name  interrel
name                    
joe    1   joe         2
mark   2  mark         1
carl   3  carl         0
person EdChum    schedule 11.05.2015