【问题标题】:How to use `str.replace()` method on all columns in a scraped Pandas dataframe?如何在抓取的 Pandas 数据框中的所有列上使用`str.replace()`方法?
【发布时间】:2015-03-13 07:25:57
【问题描述】:

我是数据分析方面的 Python/Pandas 初学者。我正在尝试从有关字母频率的维基百科文章中导入(/刮擦)表格,对其进行清理,然后将其转换为数据框。

这是我用来将表格转换为名为 letter_freq_all 的数据框的代码:

import pandas as pd
import numpy as np

letter_freq_all = pd.read_html('http://en.wikipedia.org/wiki/Letter_frequency', header=0)[4]
letter_freq_all

我想清理数据并正确格式化以进行数据分析:

  • 我想从列名中删除带有数字的方括号,并确保两边没有空白填充
  • 我还想从每一列中删除百分号和所有星号,以便将每一列转换为浮点类型。
  • 到目前为止,我没有成功尝试从所有列中删除 % 符号。

这是我试过的代码:

letter_freq_all2 = [str.replace(i,'%','') for i in letter_freq_all]

我没有得到一个没有任何 % 符号的新数据框,而是得到了 letter_freq_all 中所有列的列表:

['Letter','French [14]','German [15]','Spanish [16]','Portuguese [17]','Esperanto  [18]','Italian[19]','Turkish[20]','Swedish[21]','Polish[22]','Dutch [23]','Danish[24]','Icelandic[25]','Finnish[26]','Czech']

然后我试着去掉一列中的 % 符号:

letter_freq_all3 = [str.replace(i,'%','') for i in letter_freq_all['Italian[19]']]**

当我这样做时,str.replace 方法有点工作 - 我得到了一个没有任何 % 符号的列表(我期待得到一个系列)。

那么,我怎样才能摆脱我的数据框 letter_freq_all 中所有列中的 % 符号?另外,我怎样才能摆脱所有列中的所有括号和额外的空白填充?我猜我可能不得不使用.split() 方法

【问题讨论】:

标签: python string pandas dataframe web-scraping


【解决方案1】:

实现目标最简洁的方法是使用带有正则表达式的 str.replace() 方法:

1) 重命名列:

letter_freq_all.columns = pd.Series(letter_freq_all.columns).str.replace('\[\d+\]', '').str.strip()

2) 替换星号和百分号并转换为小数:

letter_freq_all.apply(lambda x: x.str.replace('[%*]', '').astype(float)/100, axis=1)

在这种情况下,apply() 对每一列执行 str.replace() 方法。

在此处了解有关正则表达式元字符的更多信息:

https://www.hscripts.com/tutorials/regular-expression/metacharacter-list.php

【讨论】:

    【解决方案2】:

    对于数据分析,使用 float 而不是 string 条目是有意义的。因此,您可以编写一个尝试转换每个条目的函数:

    def f(s):
        """ convert string to float if possible """
        s = s.strip()  # remove spaces at beginning and end of string
        if s.endswith('%'):  # remove %, if exists
            s = s[:-1]
        try:
            return float(s)
        except ValueError: # converting did not work
            return s  # return original string
    
    lf2 = letter_freq_all.applymap(f)  # convert all entries 
    

    【讨论】:

      【解决方案3】:

      认为这行得通。我使用 panda 的 broadcasting capabilities 一次替换 1 列(实际上是几列)中的值。

      # Ignore first col with letters in it.
      cols = letter_freq_all.columns[1:]
      
      # Replace the columns `cols` in the DF
      letter_freq_all[cols] = (
          letter_freq_all[cols]
          # Replace things that aren't numbers and change any empty entries to nan
          # (to allow type conversion)
          .replace({r'[^0-9\.]': '', '': np.nan}, regex=True)
          # Change to float and convert from %s
          .astype(np.float64) / 100
      )
      
      letter_freq_all.head()
      
      
       Letter  French [14]  German [15]  Spanish [16]  Portuguese [17]  ...
      0      a      0.07636      0.06516       0.11525          0.14634   
      1      b      0.00901      0.01886       0.02215          0.01043   
      2      c      0.03260      0.02732       0.04019          0.03882   
      3      d      0.03669      0.05076       0.05510          0.04992   
      4      e      0.14715      0.16396       0.12681          0.11570 
      

      【讨论】:

      • 谢谢你,忧郁!我试过你的代码,它工作。 :) 我想知道您是否可以更详细地解释您的代码是如何工作的。看起来您将所有带有百分号的字符串值都转换为 nan 类型。我想我对这行代码如何能够从 nan 转换为 float 有点困惑。在 .replace({r'[^0-9\.]': '', '': np.nan}, regex=True)
      • 可以给 pandas 的replace 一个由 from (keys) 和 to (values) 对组成的字典。所以在这里,我在每个值中用 '' 替换了任何不是数字的东西,并且分别用 nan 替换了空字符串。它(有点)相当于.replace(r'[^0-9\.]', '', regex=True).replace('', np.nan)
      • Nans 是浮点型。我将空单元格更改为浮点数,因此我可以使用 astype 将每个单元格转换为浮点数(因为那时我只有数字作为字符串或 nans)。
      猜你喜欢
      • 2020-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-08
      相关资源
      最近更新 更多