Как правильно вызвать функцию и вернуть обновленный фрейм данных?

#python #dataframe #apply

Вопрос:

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

 df = pd.DataFrame(['adam', 'ed', 'dra','dave','sed','mike'], index =
['a', 'b', 'c', 'd', 'e', 'f'], columns=['A'])

def get_item(data):
    comb=pd.DataFrame()
    comb['Newfield'] = data     #create new columns
    comb['AnotherNewfield'] = 'y'

return pd.DataFrame(comb)
 

Настройка функции с помощью apply:

 >>> newdf = df['A'].apply(get_item)

>>> newdf
a          A   Newfield AnotherNewfield
a  adam  st...
b          A   Newfield AnotherNewfield
e   sed  st...
c          A   Newfield AnotherNewfield
d  dave  st...
d          A   Newfield AnotherNewfield
d  dave  st...
e          A   Newfield AnotherNewfield
s   NaN  st...
f         A   Newfield AnotherNewfield
m  NaN  str(...
Name: A, dtype: object
>>> type(newdf)
<class 'pandas.core.series.Series'>
 

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

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

Тестирование немного по — другому с отдельными переменными-и возврат нескольких переменных серии ->, похоже, работает, поэтому я посмотрю, могу ли я что-то сделать в своем фактическом случае и обновить.

 def get_item(data):

    value = data     #create new columns
    AnotherNewfield = 'y'
    return pd.Series(value),pd.Series(AnotherNewfield)
df['B'], df['C'] = zip(*df['A'].apply(get_item))
 

Комментарии:

1. df['A'] = df['A'].apply(get_item)

2. Спасибо за ответ — казалось бы, это вернет только одну колонку, верно? По сути, надеялся вернуть новые столбцы, а также фрейм данных. Вы хотите сказать, что мне, возможно, потребуется сделать каждую колонку отдельно?

3. ответ драма ничего не возвращает. Он изменяет столбец 'A' фрейма данных, а не присваивает измененный ряд новому изменяемому.

4. Ваши кадры данных хранятся в столбце A , поэтому у вас есть серия кадров данных.

5. Да, похоже, что это так. Я смог приблизиться к тому, чтобы все получилось так, как я хотел (т. Е. если я создам новые столбцы, верните их), используя это: def get_item(данные): значение = данные #создайте новые столбцы AnotherNewfield = ‘y’ верните pd.Серию(значение), pd.серию(другое поле) df[‘B’], df[‘C’] = zip(*df[‘A’].примените(get_item)) -> я посмотрю, могу ли я применить это к моему фактическому коду и обновить.

Ответ №1:

Вы могли бы использовать groupby с apply , чтобы получить apply кадр данных из вызова, как это:

 import pandas as pd

# add new column B for groupby - we need single group only to do the trick
df = pd.DataFrame(
    {'A':['adam', 'ed', 'dra','dave','sed','mike'], 'B': [1,1,1,1,1,1]},
    index=['a', 'b', 'c', 'd', 'e', 'f'])

def get_item(data):
    # create empty dataframe to be returned
    comb=pd.DataFrame(columns=['Newfield', 'AnotherNewfield'], data=None)
    # append series data (or any data) to dataframe's columns 
    comb['Newfield'] = comb['Newfield'].append(data['A'], ignore_index=True)
    comb['AnotherNewfield'] = 'y'
    # return complete dataframe
    return comb

# use column B for group to get tuple instead of dataframe
newdf = df.groupby('B').apply(get_item)
# after processing the dataframe newdf contains MultiIndex - simply remove the 0-level (index col B with value 1 gained from groupby operation)
newdf.droplevel(0)
 

Выход:

     Newfield    AnotherNewfield
0   adam        y
1   ed          y
2   dra         y
3   dave        y
4   sed         y
5   mike        y
 

Ответ №2:

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

 def get_item(data):
    
    value = data     #create new columns using variables
    AnotherNewfield = 'y'
    return pd.Series(value),pd.Series(AnotherNewfield)

>>> df['B'], df['C'] = zip(*df['A'].apply(get_item))
>>> df
      A        B     C
a  adam  (adam,)  (y,)
b    ed    (ed,)  (y,)
c   dra   (dra,)  (y,)
d  dave  (dave,)  (y,)
e   sed   (sed,)  (y,)
f  mike  (mike,)  (y,)
>>>
 

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

 >>> df['B'] = df['B'].apply(lambda x: re.sub(r"[^a-zA-Z0-9-] ", ' ', str(x)))
>>> df
      A       B     C
a  adam   adam   (y,)
b    ed     ed   (y,)
c   dra    dra   (y,)
d  dave   dave   (y,)
e   sed    sed   (y,)
f  mike   mike   (y,)
>>> df['C'] = df['C'].apply(lambda x: re.sub(r"[^a-zA-Z0-9-] ", ' ', str(x)))
>>> df
      A       B    C
a  adam   adam    y 
b    ed     ed    y 
c   dra    dra    y 
d  dave   dave    y 
e   sed    sed    y 
f  mike   mike    y