#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