【问题标题】:Python: Truncating a string and combiningPython:截断字符串并组合
【发布时间】:2018-11-08 18:32:22
【问题描述】:

我想要实现的目标

我下面的代码会抓取一个网站并将数据框导出到 excel 文件。但是,我需要从第一列中删除不必要的字符并将它们组合起来,这样我就不需要在 excel 文件中重命名月份。每一行都有一个来自网站的名称,HOZ18(2018 年 12 月)'HOZ19(2019 年 12 月),除了“\”之外我不感兴趣。所以,我只想在第一列中显示 12 月 18 日、1 月 19 日、2 月 20 日等。

代码

    from urllib.request import urlopen
    import pandas as pd
    import requests
    from bs4 import BeautifulSoup

    url = "https://shared.websol.barchart.com/quotes/quote.php?page=quote&sym=ho&x=13&y=8&domain=if&display_ice=1&enabled_ice_exchanges=&tz=0&ed=0"

    res = requests.get(url)

    soup = BeautifulSoup(res.text, 'lxml')

    Contracts=[]
    LastPrice=[]


    data_rows = soup.findAll('tr')[2:]

    for td in data_rows:
       Contract = td.findAll('td')[0].text
       Contracts.append(Contract)
       LstPrice = td.findAll('td')[7].text
       LastPrice.append(LstPrice)

   df = pd.DataFrame({'Contracts': Contracts, 'Previous Settled': LastPrice})

输出(仅部分)

  0     Cash (HOY00)    2.1884
  1     Dec \'18 (HOZ18)    2.2371
  2     Jan \'19 (HOF19)    2.2238
  3     Feb \'19 (HOG19)    2.2125

【问题讨论】:

  • 澄清一下,您是否正在寻找 Python 代码来将 Dec \'18 (HOZ18) 之类的字符串更改为 December 2018
  • @DustinMichels _ 是的。这适用于 HOF19、HOG 19 等所有月份。

标签: python pandas dataframe web-scraping


【解决方案1】:

这是一个不需要.apply() 的选项。它假设我们正在处理 21 世纪的岁月,不确定这是否适合你。它还将月份存储为一个数字,这可能很有用,如果没有,您可以删除该位。

import pandas as pd
import re
import datetime

# Data setup.

data = pd.DataFrame(['Dec \'18 (HOZ18)', 'Jan \'19 (HOF19)', 'Feb \'19 (HOG19)'], columns = ['string'])

# Extract the month number using regex, then map it to a month number.

data['month_number'] = [datetime.datetime.strptime(re.sub('\s\'.*', '', i), '%b').month for i in data['string']]

# Extract the year, prepend '20' and store as an integer.

data['year'] = [int('20' + re.search('\d\d', i).group(0)) for i in data['string']]

print(data)

给予:

            string  month_number  year
0  Dec '18 (HOZ18)            12  2018
1  Jan '19 (HOF19)             1  2019
2  Feb '19 (HOG19)             2  2019

【讨论】:

    【解决方案2】:

    如果您希望将Dec \'18 (HOZ18) 之类的字符串转换为December 18,这是一种解决方案。

    1) 定义一个函数来清理字符串:

    # define a dictionary to convert short month names to full ones
    month_mapper = {
        'Jan': 'January',
        'Feb': 'February',
        'Mar': 'March',
        'Apr': 'April',
        'May': 'May',
        'Jun': 'June',
        'Jul': 'July',
        'Aug': 'August',
        'Sep': 'September',
        'Oct': 'October',
        'Nov': 'November',
        'Dec': 'December',
    }
    
    def clean_month_string(s):
        # replace the '\' char with empty string
        s = s.replace('\\', '')
    
        # split into three pieces on space
        # eg, "Dec '18 (HOZ18)" ->
        #   month = "Dec"
        #   year = "'18"
        #   code = "(HOZ18)"
        month, year, code = s.split(' ')
    
        # convert month using month mapper
        month = month_mapper[month]
    
        # remove the ' at the start of the year
        year = year.replace("'", "")
    
        # return new month and new year (dropping code)
        return ' '.join([month, year])
    

    2) 使用 apply 将该函数应用于 DataFrame 中的每一行。

    # drop that first row, which is not properly formatted
    df = df.drop(0).reset_index(drop=True)
    
    # apply the function to your 'Contracts' series.
    df['Contracts'] = df['Contracts'].apply(clean_month_string)
    

    【讨论】:

    • 谢谢。或者我可能只是想根据索引将月份添加到数据框中。可以这样做吗?因为 row1 是当前月份,依此类推。
    • 是的,这是可能的。这将大致涉及获取索引mod 12,然后在 12 个月的列表中查找该数字。
    • @I am getting error below df['Contracts'] = df['Contracts'].apply(clean_month_string) TypeError: clean_month_string() 采用 0 个位置参数,但给出了 1 个
    • 另外,哪个代码知道 row0 应该是当前月份,以此类推剩余行?
    • 我可以毫无错误地运行它。尝试从 apply 语句中删除括号:.apply(clean_month_string()) --> .apply(clean_month_string)。 Apply 基本上一次将函数应用于系列中的每一行,而不是要求您一次迭代每一行!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-03
    • 1970-01-01
    • 1970-01-01
    • 2016-11-12
    • 1970-01-01
    • 2014-09-14
    相关资源
    最近更新 更多