【问题标题】:Decode a column in a dataframe and remove "b'\xc2\xa" n "\xc2\xa0"解码数据框中的一列并删除 "b'\xc2\xa" n "\xc2\xa0"
【发布时间】:2019-06-13 04:18:56
【问题描述】:

我有两个问题。

  1. 我所有的专栏都以字母“b”开头。我想摆脱这个字符并将所有值转换为浮点数。 (我附上了整个数据框的图像)。

  1. 对于价格列,有这个额外的编码“\xc2\xa”。我想删除它并保留十进制值。 (我附上了这个专栏的图片)。

通过将列转换为字符串然后使用以下代码,我能够删除该列的“b”字符:

price.replace('b','')

但是当我用“\xc2\xa”尝试这段代码时,它不起作用。我还认为将所有列转换为字符串效率有点低,那么有什么更好的选择?

如果有帮助,这是我的全部代码:

import requests
import pandas as pd
from bs4 import BeautifulSoup

Base_url = ("https://www.nseindia.com/live_market/dynaContent/live_watch/fxTracker/optChainDataByExpDates.jsp")

page = requests.get(Base_url)

soup = BeautifulSoup(page.content, 'html.parser')
table_it = soup.find_all(class_="opttbldata")

spot = soup.select_one("div:contains('REFERENCE RATE') > strong").text
ATM = (round(float(spot)*4))/4
OTMCE = ATM + 0.50
OTMPE = ATM - 0.50

table_cls_1 = soup.find_all(id = "octable")
col_list = []

for mytable in table_cls_1:
    table_head = mytable.find('thead')

    try:
        rows = table_head.find_all('tr')
        for tr in rows:
            cols = tr.find_all('th')
            for th in cols:
                er = th.text
                ee = er.encode('utf-8')
                col_list.append(ee)
    except:
        print('no thread')

col_list_fnl = [e for e in col_list if e not in ('CALLS', 'PUTS', 'Chart', '\xc2\xa0')]

table_cls_2 = soup.find(id = "octable")
all_trs = table_cls_2.find_all('tr')
req_row = table_cls_2.find_all('tr')

df = pd.DataFrame(index=range(0,len(req_row)-3),columns = col_list_fnl)

row_marker = 0

for row_number, tr_nos in enumerate(req_row):
    if row_number <= 1 or row_number == len(req_row)-1:
        continue # To insure we only choose non empty rows

    td_columns = tr_nos.find_all('td')

    # Removing the graph column
    select_cols = td_columns[1:22]
    cols_horizontal = range(0,len(select_cols))

    for nu, column in enumerate(select_cols):

        utf_string = column.get_text()
        utf_string = utf_string.strip('\n\r\t": ')
        tr = utf_string.encode('utf-8')

        df.iloc[row_marker,[nu]] = tr

    row_marker += 1

print(df)

【问题讨论】:

  • soup = BeautifulSoup(page.content, 'html.parser') 替换为soup = BeautifulSoup(page.text, 'html.parser')。如果您不想要字节,请不要索取。
  • @cs95 我仍然在每个值之前得到'b'字符。我也希望这些值是小数而不是字符串。抱歉,我是网络抓取/数据清理的新手!
  • 这可能也是因为这条不必要的行:ee = er.encode('utf-8')
  • 还有tr = utf_string.encode('utf-8')。你为什么一直编码东西?这会将字符串转换为字节——不是你想要的,还是我弄错了?
  • @cs95 如果我删除代码:tr = utf_string.encode('utf-8'),我会收到此错误:无法将大小为 53 的序列复制到维度为 1 的数组轴。

标签: python python-3.x pandas


【解决方案1】:

我根据@cs95 和@eyllanesc 的cmets 更改了您的代码。我可以毫无错误地执行代码,它会产生一个没有字节编码的数据帧。

import requests
import pandas as pd
from bs4 import BeautifulSoup

Base_url = ("https://www.nseindia.com/live_market/dynaContent/live_watch/fxTracker/optChainDataByExpDates.jsp")

page = requests.get(Base_url)

soup = BeautifulSoup(page.text, 'html.parser')
table_it = soup.find_all(class_="opttbldata")

spot = soup.select_one("div:contains('REFERENCE RATE') > strong").text
ATM = (round(float(spot)*4))/4
OTMCE = ATM + 0.50
OTMPE = ATM - 0.50

table_cls_1 = soup.find_all(id = "octable")
col_list = []

for mytable in table_cls_1:
    table_head = mytable.find('thead')

    try:
        rows = table_head.find_all('tr')
        for tr in rows:
            cols = tr.find_all('th')
            for th in cols:
                er = th.text
                col_list.append(er)
    except:
        print('no thread')

col_list_fnl = [e for e in col_list if e not in ('CALLS', 'PUTS', 'Chart', '\xc2\xa0')]

table_cls_2 = soup.find(id = "octable")
all_trs = table_cls_2.find_all('tr')
req_row = table_cls_2.find_all('tr')

df = pd.DataFrame(index=range(0,len(req_row)-3),columns = col_list_fnl)

row_marker = 0

for row_number, tr_nos in enumerate(req_row):
    if row_number <= 1 or row_number == len(req_row)-1:
        continue # To insure we only choose non empty rows

    td_columns = tr_nos.find_all('td')

    # Removing the graph column
    select_cols = td_columns[1:22]
    cols_horizontal = range(0,len(select_cols))

    for nu, column in enumerate(select_cols):

        utf_string = column.get_text()
        utf_string = utf_string.strip('\n\r\t": ')
        tr = utf_string

        df.iloc[row_marker,[nu]] = tr

    row_marker += 1

display(df)

打印出来:

加法

要将列正确转换为唯一名称并将值正确转换为浮点值,请执行以下操作:

cols = ['_first_col', 'Chart ', 'OI', 'Change in OI', 'Volume', 'IV', 'LTP', 'BidQty',
       'BidPrice', 'AskPrice_01', 'AskQty', 'Strike Price', 'BidQty', 'BidPrice',
       'AskPrice_02', 'AskQty', 'LTP', 'IV', 'Volume', 'Change in OI', 'OI',
       'Chart']
df.columns = cols

df.AskPrice_01 = df.AskPrice_01.apply(lambda x: float(x) if x != "-" else None)

df.AskPrice_02 = df.AskPrice_02.apply(lambda x: float(x) if x != "-" else None)

要过滤特定的列,您可以使用:

df[df.AskPrice_01 > 65.25].AskPrice_01

我希望这会有所帮助。祝你的项目好运!

【讨论】:

  • 有没有办法检查“AskPrice”列是否以 65.25 开头,然后只显示该行?该列中的值似乎采用以下格式:\xa065.2500\xa0\n1
  • 要过滤特定列,您可以使用df[df.AskPrice &gt; 65.25]。我看到您有两个列名称AskPrice。您需要将其修复为唯一名称。
  • 我通过使用索引号解决了这个问题:price = df.iloc[:,9:10]。例如我想检查价格contains 的值是否为 65.5。我试过price.str.contains(65.5),但我得到一个'DataFrame'对象没有属性'str'错误
  • 查看我对答案的补充。您的值仍然是字符串或包含需要转换为 float 或 int 值的字符串。
  • 天哪,这非常有效,谢谢你所做的一切,我希望我能投票给这 1000 倍
猜你喜欢
  • 2018-02-03
  • 2015-12-01
  • 2021-04-18
  • 2016-02-25
  • 2016-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多