применить лямбда-функцию к кадру данных dask - PullRequest
0 голосов
/ 02 марта 2019

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

df = pd.DataFrame({'A':['ant','ant','cherry', 'bee', 'ant'], 'B':['cat','peach', 'cat', 'cat', 'peach'], 'C':['dog','dog','roo', 'emu', 'emu']})
ddf = dd.from_pandas(df, npartitions=2)

df:

вывод:

     A     B      C
0   ant    cat   dog
1   ant    peach dog
2   cherry cat   roo
3   bee    cat   emu
4   ant    peach emu
ddf.compute()

вывод:

     A     B      C
0   ant    cat   dog
1   ant    peach dog
2   cherry cat   roo
3   bee    cat   emu
4   ant    peach emu
list_ = ['B','C']
df.apply(lambda x: x.mask(x.map(x.value_counts(normalize=True))<.5, 'other') if x.name not in list_ else x)

вывод:

     A     B      C
0   ant    cat   dog
1   ant    peach dog
2   other  cat   roo
3   other  cat   emu
4   ant    peach emu

Сделайте то же самое для dask dataframe:

ddf.apply(lambda x: x.mask(x.map(x.value_counts(normalize=True))<.5, 'other') if x.name not in list_ else x,axis=1).compute()

вывод (выдает предупреждение, а вывод не требуется):

/home/michael/env/lib/python3.5/site-packages/dask/dataframe/core.py:3107: UserWarning: `meta` is not specified, inferred from partial data. Please provide `meta` if the result is unexpected.
  Before: .apply(func)
  After:  .apply(func, meta={'x': 'f8', 'y': 'f8'}) for dataframe result
  or:     .apply(func, meta=('x', 'f8'))            for series result
  warnings.warn(msg)
      A       B       C
0   other   other   other
1   other   other   other
2   other   other   other
3   other   other   other
4   other   other   other

Может ли кто-нибудь помочь мне получитьтребуется вывод для экземпляра dask dataframe.

Спасибо

Майкл

1 Ответ

0 голосов
/ 02 марта 2019

Вы не выполняете одно и то же в случаях с пандами и дасками: для последнего у вас есть axis=1, поэтому вы в конечном итоге заменяете любое значение, встречающееся менее чем в два раза в данной строке , чтоэто все из них.

Если вы измените на axis=0, вы увидите, что получите исключение.Это связано с тем, что для вычисления, скажем, первого раздела вам потребуется, чтобы весь массив данных также передавался в лямбда-функцию - иначе как вы могли бы получить value_counts?

Решением вашей проблемы было бы получитьзначение считается отдельно.Вы можете явно вычислить это (результат небольшой) или передать его в лямбду.Кроме того, обратите внимание, что использование этого пути означает, что вы можете избежать использования apply в пользу map и делать вещи более явными.Здесь я выбираю только один столбец, вы можете зациклить.

vc = ddf.A.value_counts().compute()
vc /= vc.sum()  # because dask's value_count doesn't normalise

def simple_map(df):
    df['A'] = df['A'].map(lambda x: x if vc[x] > 0.5 else 'other')
    return df

ddf.map_partitions(simple_map, meta=df[:0]).compute()
...