как передать аргументы в df.xs () - PullRequest
0 голосов
/ 05 декабря 2018

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

Например, функция берет словарь меток индекса и значений фильтра, а также кортеж метрик.

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

пример кода:

df = pd.DataFrame({'lab1': np.random.choice(['A','B','C'],100,replace=True), 'lab2': np.random.choice(['one','two','three','four'],100,replace=True), 'val': np.random.rand(100)})
df = df.groupby(['lab1','lab2']).sum()

                 val
lab1 lab2           
A    four   3.296221
     one    5.057798
     three  3.443166
     two    3.913044
B    four   3.815448
     one    3.892152
     three  2.995777
     two    9.715343
C    four   6.118737
     one    3.735783
     three  2.461903
     two    5.252095

ниже приведен статический пример использования .xs ():

 df.xs(('A', slice('one','three')), level=['lab1','lab2'])
                 val
lab1 lab2           
A    one    5.057798
     three  3.443166

Кажется, проблема в том, что вы не можете легко передатьперечислить аргумент в slice().Я пытался использовать pd.IndexSlice, map, lambda и т. Д., Но не могу заставить его работать.

То, что я хотел бы получить, это:

filters = {
'lab1': 'A',
'lab2' : ('one','three'),
metrics = ('val')
}
def metric_ts(filters, metrics):
    levels = list(filters.keys()) + ['metric_name']
    keys = map(slice, list(filters.values()))
    return df_norm.xs(keys, levels)

Примечание: я понимаючто есть несколько способов сделать это с помощью .loc [] и т. д. Я ищу очень общее решение, которое не опирается на позиционный синтаксис.Спасибо!

Ответы [ 2 ]

0 голосов
/ 06 декабря 2018

Я понял, как это сделать, используя метод .xs ().Хитрость заключается в том, чтобы обернуть несколько меток в slice() в фильтре, прежде чем перейти к функции.IMO Я думаю, что это немного чище, чем анализировать и использовать .query ().

Единственная проблема сейчас заключается в том, что slice() возвращает непрерывный срез на основе порядка индекса (я хочу, чтобы он только возвращал указанные значения).Надеюсь, кто-то может расширить это.

df = pd.DataFrame({'lab1': np.random.choice(['A','B','C'],100,replace=True), 'lab2': np.random.choice(['one','two','three','four'],100,replace=True), 'val': np.random.rand(100)})
df = df.groupby(['lab1','lab2']).sum()

filters = {
'lab1': slice('A','C'),
'lab2' : slice('one','two')
}

def return_slice(filters):
    slices = pd.IndexSlice[tuple(filters.values())]
    levels = list(filters.keys())
    return df.xs(key=slices, level=levels,drop_level=False)

return_slice(filters)

                 val
lab1 lab2           
A    one    3.094135
     three  4.458957
     two    6.896360
B    one    2.917692
     three  6.754484
     two    4.023079
C    one    4.464885
     three  5.982234
     two    4.421695
0 голосов
/ 05 декабря 2018

Не знаю, как бы вы сделали это с xs, но вы можете использовать DataFrame.query, если вы динамически создаете строку запроса.

filters = {
'lab1': 'A',
'lab2' : ('one','three'),
}
metrics = 'val'

globals().update(filters) 

querystr = ' and '.join([
    f"{k} {'==' if isinstance(v, (str, np.number)) else 'in'} @{k}" 
    for k, v in filters.items()])

df.query(querystr)[metrics]  

lab1  lab2 
A     one      4.041335
      three    4.923771
Name: val, dtype: float64

Подобные примеры можно увидеть здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...