Как манипулировать записями столбцов, используя только один конкретный вывод функции, которая возвращает несколько значений? - PullRequest
2 голосов
/ 04 июля 2019

У меня есть такой фрейм данных:

import numpy as np
import pandas as pd

df = pd.DataFrame({'a': range(4), 'b': range(2, 6)})

   a  b
0  0  2
1  1  3
2  2  4
3  3  5

и у меня есть функция, которая возвращает несколько значений. Здесь я просто использую фиктивную функцию , которая возвращает минимум и максимум для определенного итерируемого ввода:

def return_min_max(x):
    return (np.min(x), np.max(x))

Теперь я хочу, например, добавьте максимум каждого столбца к каждому значению в соответствующем столбце.

Итак

df.apply(return_min_max)

дает

a    (0, 3)
b    (2, 5)

, а затем

df.add(df.apply(return_min_max).apply(lambda x: x[1]))

дает желаемый результат

   a   b
0  3   7
1  4   8
2  5   9
3  6  10

Мне интересно, есть ли более простой способ избежать двух цепочек apply.

Просто чтобы убедиться:

Я НЕ заинтересован в

df.add(df.max())

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

Ответы [ 2 ]

3 голосов
/ 04 июля 2019

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

# create a dataframe for easy access
ret_df = pd.DataFrame(df.apply(return_min_max).to_dict())
#    a  b
# 0  0  2
# 1  3  5

# add 
df.add(ret_df.loc[1], axis=1)

Вывод:

   a   b
0  3   7
1  4   8
2  5   9
3  6  10

И широковещательная трансляция:

df.values[None,:] + ret_df.values[:,None]

дает:

array([[[ 0,  4],
        [ 1,  5],
        [ 2,  6],
        [ 3,  7]],

       [[ 3,  7],
        [ 4,  8],
        [ 5,  9],
        [ 6, 10]]], dtype=int64)
2 голосов
/ 04 июля 2019

DataFrame.max возвращает серию максимальных значений по столбцам.DataFrame.add() добавит это Series, выравнивая по столбцам.

df.add(df.max())

#   a   b
#0  3   7
#1  4   8
#2  5   9
#3  6  10

Если ваша реальная функция намного сложнее, есть несколько альтернатив.

Оставьте все как есть, используйте .str для доступа к элементу max.

def return_min_max(x):
    return (np.min(x), np.max(x))

df.add(df.apply(return_min_max).str[1])

Рассмотрите возможность возврата Series с индексом, описывающим возвращаемое значение:

def return_min_max(x):
    return pd.Series([np.min(x), np.max(x)], index=['min', 'max'])

df.add(df.apply(return_min_max).loc['max'])

Или, если возврат можно разделить (в этом случае max и min действительно не нужно выполнять в одной и той же функции), проще разделить их:

def return_max(x):
    return np.max(x)

df.add(df.apply(return_max))
...