在 Pandas 数据框中运行正则表达式循环
Posted
技术标签:
【中文标题】在 Pandas 数据框中运行正则表达式循环【英文标题】:Running a Regex loop in a Pandas Dataframe 【发布时间】:2017-01-16 19:08:03 【问题描述】:我目前有一个日期列存在一些问题。我已尝试解决此问题,但无法得出结论。
这是数据:
# Import data
df_views = pd.read_excel('PageViews.xlsx')
# Check data types
df_views.dtypes
Out[57]:
Date object
Customer ID int64
dtype: object
日期列未按预期采用“日期时间”数据格式。进一步检查结果:
df_views.ix[:5]
Date Customer ID
0 01/25/2016 104064596300
1 02/28/2015 102077474472
2 11/17/2016 106430081724
3 02/24/2016 107770391692
4 10/05/2016 106523680888
5 02/24/2016 107057691592
我快速检查哪些行没有遵循正确的格式 xx/xx/xxxx
print (df_views[df_views["Date"].str.len() != 10])
Date Customer ID
189513 12/14/ 106285770688
189514 10/28/ 107520462840
189515 11/01/ 102969804360
189516 11/10/ 102106417100
189517 02/16/ 107810168068
189518 10/25/ 102096164504
189519 02/08/ 107391760644
189520 02/29/ 107353558928
189521 10/24/ 107209142140
189522 12/20/ 107875461336
189523 12/23/ 107736375428
189524 11/12/ 106561080372
189525 01/27/ 102676548120
189526 11/19/ 107733043896
189527 12/31/ 107774452412
189528 01/21/ 102610956040
189529 01/09/ 108052836888
189530 02/21/ 106380330112
189531 02/02/ 107844459772
189532 12/12/ 102006641640
189533 12/16/ 106604647688
189534 11/14/ 102383102504
我试图创建一个 for 循环,但不知道如何处理我的循环。
重要提示:我知道所有观察的时间段都在 2015 年 9 月到 2016 年 2 月之间。
因此,如果月份是 09/10/11/12 - 那么我可以在日期中添加“2015”, 否则,如果月份是 01/02,我可以添加“2016”。
for row in df_views["Date"]:
if len(row) != 10:
if row.str.contains("^09|10|11|12\/"):
row.str.cat("2015")
elif row.str.contains("^01|02\/"):
row.str.cat("2016")
else:
continue
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-87-684e121dd62d> in <module>()
5 for row in df_views["Date"]:
6 if len(row) != 10:
----> 7 if row.str.contains("^09|10|11|12\/"):
8 row.str.cat("2015")
9 elif row.str.contains("^01|02\/"):
AttributeError: 'str' object has no attribute 'str'
【问题讨论】:
row
似乎是一个字符串。因此,您尝试的所有方法(包含、cat)都不太可能奏效。
避免使用 for 循环。只需直接使用您在系列上使用的.str
操作即可。您可能需要调整它们,但它会比显式迭代更快。
【参考方案1】:
作为@BrenBam has already written in the comment - 尽量避免使用循环。 Pandas 为我们提供了大量的矢量化(读取快速且高效)方法:
In [67]: df
Out[67]:
Date Customer ID
0 12/14/2001 106285770688
1 10/28/2000 107520462840
2 11/01/ 102969804360
3 11/10/ 102106417100
4 02/16/ 107810168068
5 10/25/ 102096164504
6 02/08/ 107391760644
7 02/29/ 107353558928
8 10/24/ 107209142140
9 12/20/ 107875461336
10 12/23/ 107736375428
11 11/12/ 106561080372
12 01/27/ 102676548120
13 11/19/ 107733043896
14 12/31/ 107774452412
15 01/21/ 102610956040
16 01/09/ 108052836888
17 02/21/ 106380330112
18 02/02/ 107844459772
19 12/12/ 102006641640
20 12/16/ 106604647688
21 11/14/ 102383102504
In [68]: df.ix[df.Date.str.match(r'^(?:09|10|11|12)\/\d2\/$', as_indexer=True), 'Date'] += '2015'
In [69]: df.ix[df.Date.str.match(r'^(?:01|02)\/\d2\/$', as_indexer=True), 'Date'] += '2016'
In [70]: df
Out[70]:
Date Customer ID
0 12/14/2001 106285770688
1 10/28/2000 107520462840
2 11/01/2015 102969804360
3 11/10/2015 102106417100
4 02/16/2016 107810168068
5 10/25/2015 102096164504
6 02/08/2016 107391760644
7 02/29/2016 107353558928
8 10/24/2015 107209142140
9 12/20/2015 107875461336
10 12/23/2015 107736375428
11 11/12/2015 106561080372
12 01/27/2016 102676548120
13 11/19/2015 107733043896
14 12/31/2015 107774452412
15 01/21/2016 102610956040
16 01/09/2016 108052836888
17 02/21/2016 106380330112
18 02/02/2016 107844459772
19 12/12/2015 102006641640
20 12/16/2015 106604647688
21 11/14/2015 102383102504
【讨论】:
解决方案有效,但最终在没有问题的情况下将“2015”或“2016”添加到数据框的其余部分。这个正则表达式对我有用:'^(09|10|11|12)\/\d\d\/$'
以上是关于在 Pandas 数据框中运行正则表达式循环的主要内容,如果未能解决你的问题,请参考以下文章