Понимание функций списка в команде преобразования и применения в пандахPython

Программы на Python
Ответить
Anonymous
 Понимание функций списка в команде преобразования и применения в пандах

Сообщение Anonymous »

TLDR;
Я пытаюсь понять, почему списковые методы в кадрах данных ведут себя так же, как списковые методы в Series.
По сути, в Series, если вы используете apply или Transform для списковых методов, они сначала попытаются передать каждое значение Series отдельно в функцию. Если это не сработает, они передадут в функцию всю серию. По той же логике для фрейма данных сначала в функцию должна быть передана строка/столбец или, а затем, если она не работает, должен быть передан весь фрейм данных.
Но это не так, поведение фрейма данных для функций, подобных списку, точно такое же, как и для серий: сначала проверяется отдельные значения, а затем целые столбцы. Уровень детализации не увеличивается. Я хочу понять, почему так написано. Я видел исходный код.

Подробно
Я изучаю команды Apply и Transform в pandas. Я получаю то же самое, когда предоставляется одна функция.
  • Для серий
    — Функция применяется к каждому значению.
  • Код: Выделить всё

    transform
    — функция передается команде Apply. Если это не работает, то функции передается вся серия.
[*]Для Dataframe функция применяется к каждому столбцу или строке
  • — Функция применяется к каждому столбцу/строке
  • Код: Выделить всё

    transform
    — функция передается команде Apply. Если это не работает, то функции передается весь фрейм данных.

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

by_row : False или «compat», по умолчанию «compat»
... Если func представляет собой список или набор вызываемых объектов, сначала попытается преобразовать каждую функцию в методы pandas. Если это не сработает, попытаемся снова вызвать Apply с помощью by_row="compat" и, если это не удастся, снова вызовем Apply с by_row=False (обратная совместимость)...

Теперь давайте начнем с функции Apply. И для Series, и для DataFrames все сводится к этому фрагменту исходного кода для функций, подобных спискам.

Код: Выделить всё

    def apply_compat(self):
obj = self.obj
func = self.func

if callable(func):
f = com.get_cython_func(func)
if f and not self.args and not self.kwargs:
return obj.apply(func, by_row=False)

try:
result = obj.apply(func, by_row="compat")
except (ValueError, AttributeError, TypeError):
result = obj.apply(func, by_row=False)
return result
Итак, вот пример кода, позволяющий увидеть, что сначала в функцию apply передается одно значение, а затем целая серия при использовании функций, подобных списку.

Код: Выделить всё

def func(val):
print("Val - ", val, "\nVal Type - ", type(val), "\n")
if not isinstance(val, pd.Series):
raise TypeError("Not Series")
return val.iloc[0:3]

sr = pd.Series([1,2,3,4,5])
sr.apply([func])        # passed the function as a list

--- Output
Val -  1
Val Type -  

Val -  0    1
1    2
2    3
3    4
4    5
dtype: int64
Val Type -  

func
0   1
1   2
2   3
Теперь приступим к преобразованию. Следующий исходный код помогает нам понять поведение функций, подобных спискам, в Series.

Код: Выделить всё

    def transform_str_or_callable(self, func) -> DataFrame | Series:
obj = self.obj
args = self.args
kwargs = self.kwargs

if isinstance(func, str):
return self._apply_str(obj, func, *args, **kwargs)

# Two possible ways to use a UDF - apply or call directly
try:
return obj.apply(func, args=args, **kwargs)
except Exception:
return func(obj, *args, **kwargs)
По сути, он может обрабатывать любые типы исключений при использовании apply. Итак, если я просто изменю тип исключения в своей пользовательской функции, я увижу его поведение (кроме того, мне придется вернуть всю серию, поскольку форма оси должна быть такой же, как при передаче)

Код: Выделить всё

def func(val):
print("Val - ", val, "\nVal Type - ", type(val), "\n")
if not isinstance(val, pd.Series):
raise Exception("Not Series")
return val

sr = pd.Series([1,2,3,4,5])
sr.transform([func])

--- Output
Val -  1
Val Type -  

Val -  0    1
1    2
2    3
3    4
4    5
dtype: int64
Val Type -  

func
0   1
1   2
2   3
3   4
4   5
Теперь у меня возникают сомнения относительно Dataframes. Я надеялся, что с фреймами данных все будет так: сначала попробуйте передать серию, а если это не сработает, передайте в функцию весь фрейм данных. Но это не так.

Код: Выделить всё

def func(val):
print("Val - ", val, "\nVal Type - ", type(val), "\n")
if not isinstance(val, pd.DataFrame):
raise TypeError("Not DataFrame")
return val.iloc[0:3]

df = pd.DataFrame([[1,2],[3,4],[5,6]], columns=['A', 'B'])
df.apply([func])

--- Output
Val -  1
Val Type -  

Val -  0    1
1    3
2    5
Name: A, dtype: int64
Val Type -  

TypeError: Not DataFrame
Аналогично и в преобразовании.

Код: Выделить всё

def func(val):
print("Val - ", val, "\nVal Type - ", type(val), "\n")
if not isinstance(val, pd.DataFrame):
raise Exception("Not DataFrame")
return val

df = pd.DataFrame([[1,2],[3,4],[5,6]], columns=['A', 'B'])
df.transform([func])

--- Output
Val -  1
Val Type -  

Val -  0    1
1    3
2    5
Name: A, dtype: int64
Val Type -  

ValueError: Transform function failed
Почему функция списка в DataFrame ведет себя так же, как функция Series? Я видел исходный код этого проекта. Это здесь и здесь.

Код: Выделить всё

    if is_list_like(func) and not is_dict_like(func):
func = cast(list[AggFuncTypeBase], func)
# Convert func equivalent dict
if is_series:
func = {com.get_callable_name(v) or v: v for v in func}
else:
func = dict.fromkeys(obj, func)
----

for name, how in func.items():
colg = obj._gotitem(name, ndim=1)
results[name] = colg.transform(how, 0, *args, **kwargs)
По сути, создайте словарь из имени столбца для каждой функции, а затем примените функцию преобразования к каждому столбцу. То же самое верно и для приложения.
Я хочу знать, почему он не был разработан как Series. Сначала попробуйте часть объекта, а затем передайте весь объект. Итак, сначала попробуйте использовать строку/столбец фрейма данных, а если это не слова, то передайте весь фрейм данных. Я пытаюсь что-то запомнить, но поведение методов, подобных спискам, полностью отличается от поведения методов, не похожих на списки, в кадрах данных.

Подробнее здесь: https://stackoverflow.com/questions/798 ... -in-pandas
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»