[英]Using a list of dates to pull data from one DataFrame into another in Pandas
[英]Using regex to selectively pull data into pandas dataframe
我正在使用正則表達式和熊貓來讀取文件中的文本行,並有選擇地將數據拉入數據框。
說我有以下文字
Name : "Bob" Occupation : "Builder" Age : "42" Name : "Jim" Occupation : "" Age : "25"
我想將所有這些信息提取到一個數據框中,使其看起來如下所示:
Name Occupation Age
Bob Builder 42
我想忽略閱讀有關第二人稱的任何信息,因為他們的職業是空白。
碼:
with open(txt, 'r') as txt
for line in txt:
line = line.strip
a = re.findall(r'Name : \"(\S+)\"', line)
if a:
b = re.findall(r'Occupation : \"(\S+)\"', line)
if b:
c = re.findall(r'Age : \"(\S+)\"', line)
if c:
df = df.append({'Name' : a, 'Occupation' : b, 'Age' : c}, ignore_index = True)
這將返回以下(錯誤的)數據幀
Name Occupation Age
["Bob", "Jim"] ["Builder"] ["42","25"]
我想修改此代碼,以使其永遠不會包含“ Jim”所在的情況。即,如果該人沒有“職業”,則不要將其信息讀入數據框中。 您還可以看到此代碼不正確,因為現在它說“ Jim”的職業為“ Builder”。
如果收到以下文本:
Name : "Bob" Occupation : "Builder" Age : "42" Name : "Jim" Occupation : "" Age : "25" Name : "Steve" Occupation : "Clerk" Age : "110"
產生的df為:
Name Occupation Age
["Bob", "Steve"] ["Builder", "Clerk"] ["42","110"]
這很方便,因為我不再遇到任何索引問題,因此可以將這個df擴展到我的最終目標(知道如何做):
Name Occupation Age
Bob Builder 42
Steve Clerk 110
根據您的評論,三個鍵Name
, Occupation
和Age
總是相同的順序,因此我們可以使用單個正則表達式模式檢索字段值,同時確保匹配的值是非EMPTY。 以下是使用Series.str.extractall()的示例:
# example texts copied from your post
str="""
Name : "Bob" Occupation : "Builder" Age : "42" Name : "Jim" Occupation : "" Age : "25" Name : "Steve" Occupation : "Clerk" Age : "110"
Name : "Bob" Occupation : "Builder" Age : "42" Name : "Jim" Occupation : "" Age : "25"
"""
# read all lines into one field dataframe with column name as 'text'
df = pd.read_csv(pd.io.common.StringIO(str), squeeze=True, header=None).to_frame('text')
# 3 fields which have the same regex sub-pattern
fields = ['Name', 'Occupation', 'Age']
# regex pattern used to retrieve values of the above fields. There are 3 sub-patterns
# corresponding to the above 3 fields and joined by at least one white spaces(\s+)
ptn = r'\s+'.join([ r'{0}\s*:\s*"(?P<{0}>[^"]+)"'.format(f) for f in fields ])
print(ptn)
#Name\s*:\s*"(?P<Name>[^"]+)"\s+Occupation\s*:\s*"(?P<Occupation>[^"]+)"\s+Age\s*:\s*"(?P<Age>[^"]+)"
哪里:
Name\\s*:\\s*"(?P<Name>[^"]+)"
與Name : "([^"]+)"
基本相同,但可選地0或更大冒號周圍的空白:
和一個命名的捕獲組。 "([^"]+)"
的加號+
是為了確保用雙引號引起來的值不是EMPTY,因此將跳過Jim的個人資料,因為他的職業是EMPTY。 0
, 1
和2
。 然后,您可以從Series.str.extractall()檢查結果:
df['text'].str.extractall(ptn)
Name Occupation Age
match
0 0 Bob Builder 42
1 Steve Clerk 110
1 0 Bob Builder 42
刪除1級索引,您將獲得帶有原始索引的數據框。 如果任務中使用了其他列,則可以將其重新連接到原始數據框。
df['text'].str.extractall(ptn).reset_index(level=1, drop=True)
###
Name Occupation Age
0 Bob Builder 42
0 Steve Clerk 110
1 Bob Builder 42
使用re.finditer
> re.finditer
和regex分組。
例如:
import re
import pandas as pd
s = 'Name : "Bob" Occupation : "Builder" Age : "42" Name : "Jim" Occupation : "" Age : "25"'
name = re.findall(r'Name : \"(.*)\" ', s)
occupation = re.findall(r'Occupation : \"(.*)\" ', s)
age = re.findall(r'Age : \"(.*)\" ', s)
regexPattern = re.compile(r'Name : \"(?P<name>.*?)\"\s+Occupation : \"(?P<occupation>.*?)\"\s+Age : \"(?P<age>.*?)\"')
df = pd.DataFrame([i.groupdict() for i in regexPattern.finditer(s) if len(filter(None, i.groupdict().values())) == 3])
print(df)
輸出:
age name occupation
0 42 Bob Builder
您說這些字符串具有固定的格式,首先是Name
,然后是Occupation
,然后是Age
。 您可以使用
df = pd.DataFrame()
pat = r'Name\s*:\s*"([^"]+)"\s*Occupation\s*:\s*"([^"]+)"\s*Age\s*:\s*"(\d+)"'
s='Name : "Bob" Occupation : "Builder" Age : "42" Name : "Jim" Occupation : "" Age : "25" Name : "Steve" Occupation : "Clerk" Age : "110"'
for name, occupation, age in re.findall(pat, s):
df = df.append({'Name' : name, 'Occupation' : occupation, 'Age' : age}, ignore_index = True)
輸出:
>>> df
Age Name Occupation
0 42 Bob Builder
1 110 Steve Clerk
正則表達式是
Name\s*:\s*"([^"]+)"\s*Occupation\s*:\s*"([^"]+)"\s*Age\s*:\s*"(\d+)"
參見regex演示 。 由於捕獲組中的量詞設置為+
(一次或多次出現),因此這些值永遠不會為空。 為了避免前兩個值都是空,您可以將模式更改為Name\\s*:\\s*"([^"]*[^\\s"][^"]*)"\\s*Occupation\\s*:\\s*"([^"]*[^\\s"][^"]*)"\\s*Age\\s*:\\s*"(\\d+)"
,請參見此演示 。
細節
Name
- Name
\\s*:\\s*
- :
包含0+空格 "
-雙引號 ([^"]+)
-組1:一個或多個除"
"
-雙引號 \\s*
-0+空格 Occupation\\s*:\\s*"
([^"]+)
-第2組: "
以外的一個或多個字符 "\\s*Age\\s*:\\s*"
- "
空格, Age
, :
附帶0+空格,然后"
(\\d+)
-第3組:一個或多個數字 "
-雙引號
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.