повышение скорости извлечения информации из столбцов pandas

#python #pandas #dictionary

#python #pandas #словарь

Вопрос:

У меня есть фрейм данных с примерно 200 000 точками данных и столбцом, который выглядит следующим образом (пример для 1 точки данных):

 '{"id":342,"name":"Web","slug":"technology/web","position":15,"parent_id":16,"color":6526716,"urls":{"web":{"discover":"http://www.kickstarter.com/discover/categories/technology/web"}}}'
  

Я хочу извлечь информацию об имени и пуле. Я сделал следующее:

 df["cat"], df["slug"] = np.nan, np.nan

for i in range(0, len(df.category)):
    df["cat"][i] = df.category.iloc[i].split('"name":"')[1].split('"')[0]
    df["slug"][i] = df.category.iloc[i].split('"name":"')[1].split('"')[4]
  

Это работает отлично, но занимает около 4 часов. Есть ли какой-либо способ ускорить это?

Комментарии:

1. Как создается фрейм данных?

Ответ №1:

Вместо того, чтобы напрямую манипулировать фреймом данных, попробуйте использовать простые типы данных и создайте фрейм данных за один раз. Другое решение, отличное от jezrael’s:

 import json

cat, slug = [], []

for row in df.category:
    d = json.loads(row)
    cat.append(d['cat'])
    slug.append(d['slug'])

df = pd.DataFrame({'cat': cat, 'slug': slug})
  

Ответ №2:

Вы можете сделать это очень эффективно с extract и регулярными выражениями:

 df['cat'] = df['category'].str.extract('"name":"([^"] )"')
df['slug'] = df['category'].str.extract('"slug":"([^"] )"')

df
  

Вопрос был об улучшении скорости, поэтому вот сравнение производительности (протестировано на примере 100 000 строк; см. Примечание ниже):

 %%timeit

df['cat'] = df['category'].str.extract('"name":"([^"] )"')
df['slug'] = df['category'].str.extract('"slug":"([^"] )"')

309 ms ± 10.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
  
 %%timeit

cat, slug = [], []
for row in df.category:
    d = json.loads(row)
    cat.append(d['name'])
    slug.append(d['slug'])

df1 = pd.DataFrame({'cat': cat, 'slug': slug})

574 ms ± 6.57 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
  
 %%timeit

df1 = pd.DataFrame([ast.literal_eval(x) for x in df['category']],
                   index=df.index)[['name','slug']]

5.1 s ± 29 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
  

Примечание: пример, созданный с:

 x = '{"id":342,"name":"Web","slug":"technology/web","position":15,"parent_id":16,"color":6526716,"urls":{"web":{"discover":"http://www.kickstarter.com/discover/categories/technology/web"}}}'
df = pd.DataFrame({'category': [x]*100000})