问题 :
我有一个 Pandas 数据框,我试图从中提取特定的行。我感兴趣的行是那些包含日期的行,以及紧跟在带有日期的行之后的行。重要的是,我想将信息从日期后面的行移动到包含日期的行中的新列。通过这样做,我将在同一行上获得“一个人”的信息。明确地说,我想找到包含日期的行,并将信息从日期后面的行移动到新列中包含日期的行。
从这里:
Col0 Col1 Col2 Col3 Col4 Col5
0 NaN NaN NaN NaN NaN
1 *1/23/20 Joe G USA NaN G5 paper
2 NaN get_me NaN NaN NaN
3 +1/5/20 Frank F CAN NaN F4 Paper
4 NaN get_me_2 NaN NaN NaN
对此: Col0 Col1 Col2 Col3 Col4 Col5 Col6(New column)
0 1/23/20 Joe G USA NaN G5 paper get_me
1 1/5/20 Frank F CAN NaN F4 paper get_me_2
换种说法 :我基本上只是想获取所有日期行以获取下一行的信息,因此对于每个日期都有一个人,然后他们的所有信息都在一行上。如果第二行中的所有信息都在其前一行的同一列中,则可以。注意事项 :通常(但不总是)日期前有“*”或“+”字符(例如,**1/12/12 或 +5/5/20)。我首先尝试匹配包含日期的行。其中只有一个,但一个日期有一个名称“附加”(例如 *1/1/20Dev)。我想知道包含日期的列(日期总是在同一列中)是否有任何其他“废话”。这将是锦上添花,但这不是我遇到的核心问题。
第二行通常只有一个项目,但如果有更多,我可以稍后处理。我只需要同一行上的所有“人员”信息。我正在通过 PDF 读取原始数据,并试图对其进行清理。
我试过的 :我首先尝试匹配包含“类似日期”的字符串的字符串。实际上,这些都将在 Pandas 数据帧行中,但似乎正则表达式只适合获取包含日期的行(为此我可以立即获取该行并将其内容移动到包含日期的行上)
import re
search_in = '*1/4/13'
wanted_regex = r'(\d+/\d+/\d+)'
match = re.search(wanted_regex, search_in)
match.group(1)
输出 :'1/4/13'一个很好的例子 :
def regex_filter(myregex, val):
if val:
mo = re.search(myregex,val)
if mo:
return True
else:
return False
else:
return False
df_filtered =
df[df['col'].apply(regex_filter)]
是什么赋予了? 以上是我相信我正在尝试做的一个很好的例子,但我真的被难住了,我真的不知道我应该如何控制代码中的位置来获取下一行并将其向上移动。我看到很多类似的问题,但我无法确定是否应该分组、过滤、查询...?如果你能提供一个简短的理论,说明你为什么选择你选择的东西来解决这个问题,那么对于将来如何思考这个问题会非常有帮助。这就是我现在所处的位置,可以真正使用一些建议。谢谢你。
最佳答案
首先,从 pandas.Series.str.extract
开始获取类似日期的字符串:
s = df["Col1"].str.extract("(\d+/\d+/\d+)", expand=False)
然后使用 pandas.to_datetime
实际过滤掉有效日期:s = pd.to_datetime(s, dayfirst=True, errors="coerce")
# errors="coerce" to transform invalid strings
到目前为止产生:0 NaT
1 2020-01-23
2 NaT
3 2020-05-01
4 NaT
Name: Col1, dtype: datetime64[ns]
然后使用 pandas.Series.ffill
与 limit==1
获取有效日期和 右下一行 :df["Col1"] = s.ffill(limit=1)
df = df.dropna(subset=["Col1"])
print(df)
所以我们有想要的行和他们的下一行: Col0 Col1 Col2 Col3 Col4 Col5
1 1 2020-01-23 Joe G USA NaN G5 paper
2 2 2020-01-23 get_me NaN NaN NaN
3 3 2020-05-01 Frank F CAN NaN F4 Paper
4 4 2020-05-01 get_me_2 NaN NaN NaN
最后,使用 pandas.DataFrame.groupby
迭代和解开 Col2
只要:dfs = []
for k,d in df.groupby("Col1"):
dfs.append(d.assign(tmp=["Col2", "Col6"]).pivot("Col1", "tmp", "Col2").merge(d))
new_df = pd.concat(dfs).sort_index(1).reset_index(drop=True)
print(new_df)
最终输出: Col1 Col2 Col3 Col4 Col5 Col6
0 2020-01-23 Joe G USA NaN G5 paper get_me
1 2020-05-01 Frank F CAN NaN F4 Paper get_me_2
groupby
背后的逻辑部分:groupby
:为每个日期透视数据框的子集d.assign(...)
: 保持原来的 colname Col2
并根据需要命名新列,Col6
pivot
: 解开 Col2
.与 assign
和 pivot
,子集看起来像: tmp Col2 Col6
Col1
2020-05-01 Frank F get_me_2
关于pandas - 如何使用正则表达式在 Pandas 数据框中选择一行和包含特定子字符串的行后面的固定行数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65029838/