2014-09-15 2 views
2

Я пытаюсь создать PandasDataFrame путем итерации по данным в soup (от BeautifulSoup4). This SO post предложил использовать метод .loc для создания Set With Englargement для создания DataFrame.Создание DataFrame с использованием .loc для установки с увеличением

Однако этот метод занимает много времени (около 8 минут для df из 30 000 строк и 5 столбцов). Есть ли более быстрый способ сделать это. Вот мой код:

import requests 
from bs4 import BeautifulSoup 
import pandas as pd 

url = "http://api.turfgame.com/v3/zones" 
r = requests.get(url) 
soup = BeautifulSoup(r.content) 

col_names = ["name", "lat", "lng", "points_take", "points_hold"] 
dfi = pd.DataFrame(columns=col_names) 

def get_all_zones(): 

    for attr in soup.find_all("zone"): 
     col_values= [attr.get("name"), attr.get("lat"), attr.get("lng"), attr.get("points_take"), attr.get("points_hold")] 
     pos = len(dfi.index) 
     dfi.loc[pos] = col_values 

    return dfi 

get_all_zones() 
+1

использовать словарь, где ключи являются имена столбцов и значения являются столбцами в виде списков (без серий или фреймов). один раз, у вас есть все, передайте словарь на 'pd.DataFrame' –

ответ

4

Избегайте

df.loc[pos] = row 

всякий раз, когда это возможно. Pandas NDFrames хранит базовые данные в блоках (общего типа dtype), которые (для DataFrames) связаны с столбцами. DataFrames основанные на столбцах структуры данных, а не основанные на строке структуры данных.

Чтобы получить доступ к строке, DataFrame должен получить доступ к каждому блоку, выбрать соответствующую строку и скопировать данные в новую серию.

Добавление строки в существующий DataFrame также является медленным, так как новая строка должна быть добавлена ​​к каждому блоку, а новые данные копируются в новую строку. Хуже того, блок данных должен быть смежным в памяти. Поэтому добавление новой строки может заставить Pandas (или NumPy) выделить целый новый массив для блока и все данные для этого блока должны быть скопированы в массив большего размера, чтобы разместить эту одну строку. Все это копирование делает вещи очень медленными. Поэтому избегайте его, если это возможно.

Решение в данном случае состоит в добавлении данных в список Python и создать DataFrame одним махом в конце:


import requests 
from bs4 import BeautifulSoup 
import pandas as pd 

url = "http://api.turfgame.com/v3/zones" 
r = requests.get(url) 
soup = BeautifulSoup(r.content) 

col_names = ["name", "lat", "lng", "points_take", "points_hold"] 
data = []  

def get_all_zones():  
    for attr in soup.find_all("zone"): 
     col_values = [attr.get("name"), attr.get("lat"), attr.get(
      "lng"), attr.get("points_take"), attr.get("points_hold")] 
     data.append(col_values) 
    dfi = pd.DataFrame(data, columns=col_names) 

    return dfi 

dfi = get_all_zones() 
print(dfi) 
Смежные вопросы