Выбор значений из каждого столбца отдельно

python #web-scraping #beautifulsoup

#python #веб-очистка #beautifulsoup

Вопрос:

Мне нужно написать скрипт, который суммирует значения из каждого столбца (каждый столбец — отдельный день). Кроме того, я хочу разделить значения на запланированные (синий цвет) и незапланированные (красный цвет). В HTML-коде я обнаружил, что незапланированные значения имеют имя класса как «colBox cal-unplanned», а запланированные значения имеют имя класса как «colBox cal-planned».

Мой код:

 import pandas as pd
import requests
from bs4 import BeautifulSoup

URL = 'http://gpi.tge.pl/zestawienie-ubytkow' 
page = requests.get(URL)
soup = BeautifulSoup(page.content, 'html.parser')

# Here I tried to convert the data into a dataframe, but then you don't know which values are planned and which are unplanned

table = soup.find_all('table')
df = pd.read_html(str(table),header=2)[0]

# Here the values are correct, but they are collected from the whole table 
sum = 0
for tr in soup.find_all('td', class_='colBox cal-unplanned'):
    val = int(tr.text)
    sum  = val
print(sum)

for tr in soup.find_all('td', class_='colBox cal-planned'):
    print(tr.text)
 

И вот мой вопрос. Как я могу выбирать значения из каждого столбца отдельно

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

1. Итак, вы хотите получить сумму синего, а затем сумму красного для каждого столбца?

Ответ №1:

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

Но вы правы, вы теряете этот атрибут при его разборе .read_html() .

Это работает, но не уверен, насколько это надежно для вашей ситуации.

 import pandas as pd
import requests
from bs4 import BeautifulSoup

URL = 'http://gpi.tge.pl/zestawienie-ubytkow' 
page = requests.get(URL)
soup = BeautifulSoup(page.content, 'html.parser')

table = soup.find('table')

data = {}
headers = [x.text.strip() for x in table.find_all('tr')[2].find_all('th')]
for header in headers:
    data[header] = {'planned':[],
                    'unplanned':[]}

rows = table.find_all('tr')[3:]
for row in rows:
    tds = row.find_all('td')[3:len(headers) 3]
    for idx, value in enumerate(tds):
        if value.has_attr("class"):
            if 'cal-planned' in value['class']:
                data[headers[idx]]['planned'].append(int(value.text.strip()))
            elif 'cal-unplanned' in value['class']:
                data[headers[idx]]['unplanned'].append(int(value.text.strip()))


sum_of_columns = {}
for col, values in data.items():
    planned_sum = sum(values['planned'])
    unplanned_sum = sum(values['unplanned'])
    
    sum_of_columns[col] = {'planned':planned_sum,
                           'unplanned':unplanned_sum}

   
df = pd.DataFrame.from_dict(sum_of_columns,orient="columns" )  
 

Вывод:

 print(df.to_string())
           Cz 14  Pt 15  So 16  N 17  Pn 18  Wt 19  Śr 20  Cz 21  Pt 22  So 23  N 24  Pn 25  Wt 26  Śr 27
planned     8808   8301   7750  6863   6069   6199   6069   5627   5627   5695  5695   5235   5235   5376
unplanned   2320   2020   2313  2783    950    950    950    950    950    950   950    910    910    910
 

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

1. Это отлично работает. Большое вам спасибо за ваш ответ

Ответ №2:

Итак, если я правильно понял, вы хотите работать с отдельными столбцами вашего фрейма данных? Вы можете попытаться использовать это df['column_name'] для доступа к определенному столбцу df, а затем отфильтровать этот столбец для значения, которое вы хотите использовать, например

 df['column_name'] == filter_value
 

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

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

1. Это не решает мою проблему с разделением значений на запланированные значения (те, которые имеют синий фон на странице) и незапланированные значения (те, которые имеют красный фон на странице). После создания фрейма данных я теряю возможность разделения. Мне нужно разделить значения с помощью html-тегов — colBox cal-незапланированный и colBox cal-запланированный

Ответ №3:

Не уверен, обязательно ли это проблема для bs4, потому что я думаю, что информация уже находится в DataFrame в виде суммы.

Как получить доступ?

Взгляните на tail() свой фрейм данных:

 df.tail(3)
 

Пример

 import pandas as pd

URL = 'http://gpi.tge.pl/zestawienie-ubytkow' 

df = pd.read_html(URL,header=2)[0]
df.tail(3).iloc[:,2:]
 

Вывод

     Moc Osiągalna (MW)  Cz 14   Pt 15   So 16   N 17    Pn 18   Wt 19   Śr 20   Cz 21   Pt 22   So 23   N 24    Pn 25   Wt 26   Śr 27
219 Planowane           11279   10604   8391    6863    6069    6432    6069    5627    5627    5695    5695    5235    5235    5376
220 Nieplanowane        5520    5620    2313    2783    950 950 950 950 950 950 950 910 910 910
221 Łącznie ubytki      16799   16224   10704   9646    7019    7382    7019    6577    6577    6645    6645    6145    6145    6286
 

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

1. Спасибо за ваш ответ. К сожалению, сводка в таблице отличается от реальных результатов. Если мы посчитаем это вручную, результаты будут меньше

2. Это была бы альтернатива, и, надеюсь, отдельные значения, по крайней мере, будут правильными 😉 Такая информация должна быть включена в вопрос в следующий раз, это было бы здорово.

3. Вы правы. Я запомню это в следующий раз