2015-06-18 5 views
3

Я использую Pandas как способ записи данных из Selenium.Pandas написать переменное количество новых строк из списка в серии

Два примера результаты из окна поиска ac_results на веб-странице:

#Search for product_id = "01" 
ac_results = "Orange (10)" 

#Search for product_id = "02" 
ac_result = ["Banana (10)", "Banana (20)", "Banana (30)"] 

Orange возвращает только один цена ($ 10), в то время как банан возвращает переменное число цен от разных производителей, в данном примере три цены ($ 10), (20 долл. США), (30 долл. США).

Код использует regex через re.findall, чтобы захватить каждую цену и поместить их в список. Код работает нормально, пока re.findall находит только один элемент списка, как для апельсинов. Проблема в том, когда есть переменное количество цен, как при поиске Бананов. Я хотел бы создать новую строку для каждой заявленной цены, а строки должны также включать product_id и item_name.

Выходной ток:

product_id  prices     item_name 
01    10      Orange 
02    [u'10', u'20', u'30'] Banana 

Желаемый результат:

product_id  prices     item_name 
01    10      Orange 
02    10      Banana 
02    20      Banana 
02    30      Banana 

Текущий код:

df = pd.read_csv("product_id.csv") 
def crawl(product_id): 
    #Enter search input here, omitted 
    #Getting results: 
    search_result = driver.find_element_by_class_name("ac_results") 
    item_name = re.match("^.*(?=(\())", search_result.text).group().encode("utf-8") 
    prices = re.findall("((?<=\()[0-9]*)", search_reply.text) 
    return pd.Series([prices, item_name]) 

df[["prices", "item_name"]] = df["product_id"].apply(crawl) 
df.to_csv("write.csv", index=False) 

FYI: Работающие решение с csv модулем, но я хочу использовать Pandas.

with open("write.csv", "a") as data_write: 
    wr_data = csv.writer(data_write, delimiter = ",") 
    for price in prices: #<-- This is the important part! 
     wr_insref.writerow([product_id, price, item_name]) 
+0

В основном все, что нужно сделать, это панды эквивалент 'csv' модуля: ' за цену цен: wr_insref.writerow ([product_id, цена, item_name]) '(см. Выше) Это означает дублирование значений из cols 'product_id' и' tem_name', если в списке «цены» есть элементы. – Winterflags

+0

Я извлекаю «цены» через re.findall как список из активного окна поиска. Однако он не должен записывать весь список в ячейку, что он делает прямо сейчас. – Winterflags

ответ

3
# initializing here for reproducibility 
pids = ['01','02'] 
prices = [10, [u'10', u'20', u'30']] 
names = ['Orange','Banana'] 
df = pd.DataFrame({"product_id": pids, "prices": prices, "item_name": names}) 

следующая сни ppet должен работать после вашего apply(crawl).

# convert all of the prices to lists (even if they only have one element) 
df.prices = df.prices.apply(lambda x: x if isinstance(x, list) else [x]) 

# Create a new dataframe which splits the lists into separate columns. 
# Then flatten using stack. The explicit MultiIndex allows us to keep 
# the item_name and product_id associated with each price. 
idx = pd.MultiIndex.from_tuples(zip(*[df['item_name'],df['product_id']]), 
           names = ['item_name', 'product_id']) 
df2 = pd.DataFrame(df.prices.tolist(), index=idx).stack() 

# drop the hierarchical index and select columns of interest 
df2 = df2.reset_index()[['product_id', 0, 'item_name']] 
# rename back to prices 
df2.columns = ['product_id', 'prices', 'item_name'] 
+0

Спасибо за предложение! Я попытаюсь реализовать это, но может быть несколько hickup. Во-первых, я получаю объект AttributeError: DataFrame, у которого нет атрибута «цены». Обратите внимание, что я получаю «цены» не путем ручного ввода его в 'df', а путем:' prices = re.findall ("((? <= \() [0-9] *)", ac_result.text) 'from webpage. – Winterflags

+0

Также возможно объединить все это с' def crawl (product_id): 'и' df [["prices", "item_name"]] = df ["product_id"]. apply (crawl) 'как показано в вопросе?' Product_id' извлекается из 'df = pd.read_csv (" product_id.csv ")'. – Winterflags

+0

Я начинаю с 'df', как определено во второй-последней строке вашего кода, после того, как вы уже выполнили' df [["prices", "item_name"]] = df ["product_id"]. применить (ползать) '. Мое решение должно работать оттуда. Вероятно, вы могли бы изменить 'crawl' напрямую, но я не буду пытаться это сделать, потому что у меня нет доступа к тем же данным запроса, что и вы. – abeboparebop

0

я не смог запустить свой код (возможно, отсутствуют входы), но вы, вероятно, можете превратить ваш prices список в списке Словаря, а затем построить DataFrame оттуда:

d = [{"price":10, "product_id":2, "item_name":"banana"}, 
     {"price":20, "product_id":2, "item_name":"banana"}, 
     {"price":10, "product_id":1, "item_name":"orange"}] 
df = pd.DataFrame(d) 

Тогда df является:

item_name price product_id 
0 banana  10   2 
1 banana  20   2 
2 orange  10   1 
+0

Спасибо, но бананы и апельсины здесь просто примеры. В действительности, это будет любое возможное имя и цена, поэтому я не могу создать для него словарь. – Winterflags

Смежные вопросы