Применить функцию медленно в dataframe - PullRequest
0 голосов
/ 16 мая 2018

У меня есть датафрейм, который выглядит так:

>> df      
  A
0 [{k1:v1, k2:v2}, {k1:v3, k2:v4}]
1 [{k1:v5, k2:v6}, {k1:v7, k2:v8}, {k1:v9, k2:v10}]

то есть столбец A - это список диктовок с одинаковыми ключами

и я хочу извлечь значения, соответствующие первому вхождению в этих списках:

  K1 K2 A
0 v1 v2 ...
1 v5 v6 ...

мое решение пока работает, но особенно медленно (> 1 мин для ~ 50K записей):

def extract_first_dict(s):
    s['K1'] = s['A'][0]['k1']
    s['K2'] = s['A'][0]['k2']
    return s
df = df.apply(extract_first_dict, axis = 1)

Кто-нибудь может предложить лучший, более быстрый способ сделать это? Спасибо!

Ответы [ 3 ]

0 голосов
/ 16 мая 2018

Вариант 1

df.A.str[0].apply(pd.Series)

   k1  k2
0  v1  v2
1  v5  v6

с join

df.A.str[0].apply(pd.Series).join(df)

   k1  k2                                                  A
0  v1  v2  [{'k1': 'v1', 'k2': 'v2'}, {'k1': 'v3', 'k2': ...
1  v5  v6  [{'k1': 'v5', 'k2': 'v6'}, {'k1': 'v7', 'k2': ...    ​

Вариант 2

pd.DataFrame([t[0] for t in df.A], df.index)

   k1  k2
0  v1  v2
1  v5  v6

с join

pd.DataFrame([t[0] for t in df.A], df.index).join(df)

   k1  k2                                                  A
0  v1  v2  [{'k1': 'v1', 'k2': 'v2'}, {'k1': 'v3', 'k2': ...
1  v5  v6  [{'k1': 'v5', 'k2': 'v6'}, {'k1': 'v7', 'k2': ...

​
0 голосов
/ 16 мая 2018

concat

pd.concat([pd.DataFrame(df.A.str[0].tolist(), index=df.index), df], axis=1)

   k1  k2                                                  A
0  v1  v2  [{'k1': 'v1', 'k2': 'v2'}, {'k1': 'v3', 'k2': ...
1  v5  v6  [{'k1': 'v5', 'k2': 'v6'}, {'k1': 'v7', 'k2': ...
0 голосов
/ 16 мая 2018

Вариант 1

Вы должны найти pd.Series.apply более эффективным, чем pd.DataFrame.apply, поскольку вы используете только одну серию в качестве входа.

def extract_first(x):
    return list(x[0].values())

df['B'] = df['A'].apply(extract_first)

Вариант 2

Вы также можете попробовать использовать понимание списка:

df['B'] = [list(x[0].values()) for x in df['A']]

В обоих вышеупомянутых случаях вы можете разбить на 2 столбца с помощью:

df[['C', 'D']] = df['B'].apply(pd.Series)

Вы должны сравнить свои данные с данными, чтобы оценить, достаточно ли быстро работает любой из этих вариантов для вашего варианта использования.

Но на самом деле ...

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

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