【问题标题】:Vectorized format function for Pandas seriesPandas 系列的矢量化格式函数
【发布时间】:2014-03-31 09:39:41
【问题描述】:

假设我以 Series 的未格式化电话号码(作为字符串)开头,我想将它们格式化为 (XXX) YYY-ZZZZ。

我可以使用正则表达式和str.matchstr.extract 获取输入的子组件。我可以使用以下任一结果执行格式化:

ser = pd.Series(data=['1234567890', '2345678901', '3456789012']) 

matched = ser.str.match(r'(\d{3})(\d{3})(\d{4})')

extracted = ser.astype(str).str.extract(r'(?P<first>\d{3})(?P<second>\d{3})(?P<third>\d{4})')

formatmatched = matched.apply(lambda x: '({0}) {1}-{2}'.format(*x))
print 'formatmatched'
print formatmatched

formatextracted = extracted.apply(lambda x: '({first}) {second}-{third}'.format(**x.to_dict()), axis=1)
print 'formatextracted'
print formatextracted

结果:

formatmatched
0    (123) 456-7890
1    (234) 567-8901
2    (345) 678-9012
dtype: object
formatextracted
0    (123) 456-7890
1    (234) 567-8901
2    (345) 678-9012
dtype: object

是否有一种矢量化方式可以在任一上下文中应用该格式化命令?

【问题讨论】:

标签: python string formatting pandas


【解决方案1】:

您可以直接使用Series.str.replace()

In [47]: s = pandas.Series(["1234567890", "5552348866", "13434"])

In [49]: s
Out[49]: 
0    1234567890
1    5552348866
2         13434
dtype: object

In [50]: s.str.replace(r"(\d{3})(\d{3})(\d{4})", r"(\1) \2-\3")
Out[50]: 
0    (123) 456-7890
1    (555) 234-8866
2             13434
dtype: object

您还可以想象先进行另一个转换以删除任何非数字字符。

【讨论】:

  • 等等,我在@AndyHayden 之前想出了一些东西?! ;)
  • 这是我知道的解决方案。仍然需要通过replace 了解所有可能性。更一般地说,str.replace 可以处理命名组吗?
  • @DJ_8one6 是的,语法与 re.sub 相同:s.str.replace('^(?P&lt;a&gt;\d{3})(?P&lt;b&gt;\d{3})(?P&lt;c&gt;\d{4})$', r'\g&lt;a&gt; \g&lt;b&gt;-\g&lt;c&gt;')
【解决方案2】:

你为什么不试试这个:

import pandas as pd
ser = pd.Series(data=['1234567890', '2345678901', '3456789012']) 
def f(val):
    return '({0}) {1}-{2}'.format(val[:3],val[3:6],val[6:])
print ser.apply(f)

【讨论】:

  • 正在尝试处理正则表达式最能处理的更一般的问题。
  • OK,但是思路是一样的,只是在函数内部使用正则表达式的方式。希望它有所帮助:)
猜你喜欢
  • 1970-01-01
  • 2017-04-06
  • 1970-01-01
  • 2021-12-06
  • 2018-05-13
  • 2019-01-19
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
相关资源
最近更新 更多