根据数据框中的子字符串提取部分字符串 - python
Extracting parts of a string based on substrings in a dataframe - python
我正在尝试提取一些 NBA 数据,但我的数据框有一个列,其中所有统计数据都在一个字符串中,由 Stats 列中的空格分隔,如图所示:例如。 29pt 15rb 3as 1bl ...等等。我想提取每个统计数据的值,以便我有一个用于得分、篮板、助攻、盖帽等的列。我 运行 遇到的问题是有些行可能不包含所有统计数据。例如,如果一名球员没有获得任何助攻,他们在统计数据列中的值可能如下所示:14pt 3rb 2bl。我无法提取每个统计数据所需的值,尤其是当该玩家不存在该统计数据时。我试图拆分字符串,以便将其值放入列表中,这很有希望,但我仍然无法弄清楚如何获取每个统计数据的值(如果该玩家甚至存在该统计数据)。任何建议、想法或指导将不胜感激。谢谢
SM
也许是这样的?
def parse_stat(stat):
"""takes 29pt and returns (int stat_value, str stat) as (29, "pt")"""
i = 0
while i < len(stat) and stat[i].isdigit():
i += 1
return int(stat[:i]), stat[i:]
def parse(string):
substrings = string.split(' ')
stats = {}
for sub in substrings:
val, stat = parse_stat(sub)
stats[stat] = val
return stats
if __name__ == "__main__":
string = "9pt 15rb 3as 1bl"
result = parse(string)
print(result)
print(result.get("pt", 0))
print(result.get("fake", 0))
In: "9pt 15rb 3as 1bl"
Out: {'pt': 9, 'rb': 15, 'as': 3, 'bl': 1}
In: result.get("pt", 0)
Out: 9
In: result.get("fake", 0)
Out: 0
我们可以使用 Series.str.findall
to extract the values (regex explained here) 逐步执行此操作,然后将其转换为 dict
,我们将其返回到具有统计信息作为列标签和值的 DataFrame。
>>> import pandas as pd
>>> s = pd.Series(["29pt 15rb 3as 1bl", "14pt 3rb 2bl"])
>>> s
# 0 29pt 15rb 3as 1bl
# 1 14pt 3rb 2bl
>>> df = pd.DataFrame(
s.str.findall(r"(\d+)(\w+)")
.apply(lambda y: {k: v for v, k in y})
.to_list()
)
>>> df = df.apply(pd.to_numeric)
>>> df
# pt rb as bl
# 0 29 15 3.0 1
# 1 14 3 NaN 2
然后可以将此 DataFrame 合并到您在索引上匹配的原始 DataFrame。
s.str.findall(r"(\d+)(\w+)")
此行应用定义两个捕获组(括号 ()
)的正则表达式 r"(\d+)(\w+)"
。第一个捕获组查找数字(\d+
),第二个捕获组查找单词字符(\w+
,相当于[a-zA-Z0-9_]
†) .使用 findall
returns 元组列表,例如
"29pt 15rb 3as 1bl" => [('29', 'pt'), ('15', 'rb'), ('3', 'as'), ('1', 'bl')]
接下来,.apply(lambda y: {k: v for v, k in y})
被链接起来,在每一行上应用 lambda
函数。此函数将元组列表转换为字典,其中键是上面元组的第二个元素(pt、rb、...),值是数字。
[('29', 'pt'), ('15', 'rb'), ('3', 'as'), ('1', 'bl')]
# becomes
{'pt': '29', 'rb': '15', 'as': '3', 'bl': '1'}
最后,.to_list()
将我们的 pd.Series
转换为字典列表,我们可以使用它来创建一个可与原始数据合并的 DataFrame。
† 由于 \w+
是匹配任何字母、数字或下划线的贪婪标记,因此最好使用 [a-zA-Z]+
代替,它只会匹配字母。
我正在尝试提取一些 NBA 数据,但我的数据框有一个列,其中所有统计数据都在一个字符串中,由 Stats 列中的空格分隔,如图所示:例如。 29pt 15rb 3as 1bl ...等等。我想提取每个统计数据的值,以便我有一个用于得分、篮板、助攻、盖帽等的列。我 运行 遇到的问题是有些行可能不包含所有统计数据。例如,如果一名球员没有获得任何助攻,他们在统计数据列中的值可能如下所示:14pt 3rb 2bl。我无法提取每个统计数据所需的值,尤其是当该玩家不存在该统计数据时。我试图拆分字符串,以便将其值放入列表中,这很有希望,但我仍然无法弄清楚如何获取每个统计数据的值(如果该玩家甚至存在该统计数据)。任何建议、想法或指导将不胜感激。谢谢
SM
也许是这样的?
def parse_stat(stat):
"""takes 29pt and returns (int stat_value, str stat) as (29, "pt")"""
i = 0
while i < len(stat) and stat[i].isdigit():
i += 1
return int(stat[:i]), stat[i:]
def parse(string):
substrings = string.split(' ')
stats = {}
for sub in substrings:
val, stat = parse_stat(sub)
stats[stat] = val
return stats
if __name__ == "__main__":
string = "9pt 15rb 3as 1bl"
result = parse(string)
print(result)
print(result.get("pt", 0))
print(result.get("fake", 0))
In: "9pt 15rb 3as 1bl"
Out: {'pt': 9, 'rb': 15, 'as': 3, 'bl': 1}
In: result.get("pt", 0)
Out: 9
In: result.get("fake", 0)
Out: 0
我们可以使用 Series.str.findall
to extract the values (regex explained here) 逐步执行此操作,然后将其转换为 dict
,我们将其返回到具有统计信息作为列标签和值的 DataFrame。
>>> import pandas as pd
>>> s = pd.Series(["29pt 15rb 3as 1bl", "14pt 3rb 2bl"])
>>> s
# 0 29pt 15rb 3as 1bl
# 1 14pt 3rb 2bl
>>> df = pd.DataFrame(
s.str.findall(r"(\d+)(\w+)")
.apply(lambda y: {k: v for v, k in y})
.to_list()
)
>>> df = df.apply(pd.to_numeric)
>>> df
# pt rb as bl
# 0 29 15 3.0 1
# 1 14 3 NaN 2
然后可以将此 DataFrame 合并到您在索引上匹配的原始 DataFrame。
s.str.findall(r"(\d+)(\w+)")
此行应用定义两个捕获组(括号 ()
)的正则表达式 r"(\d+)(\w+)"
。第一个捕获组查找数字(\d+
),第二个捕获组查找单词字符(\w+
,相当于[a-zA-Z0-9_]
†) .使用 findall
returns 元组列表,例如
"29pt 15rb 3as 1bl" => [('29', 'pt'), ('15', 'rb'), ('3', 'as'), ('1', 'bl')]
接下来,.apply(lambda y: {k: v for v, k in y})
被链接起来,在每一行上应用 lambda
函数。此函数将元组列表转换为字典,其中键是上面元组的第二个元素(pt、rb、...),值是数字。
[('29', 'pt'), ('15', 'rb'), ('3', 'as'), ('1', 'bl')]
# becomes
{'pt': '29', 'rb': '15', 'as': '3', 'bl': '1'}
最后,.to_list()
将我们的 pd.Series
转换为字典列表,我们可以使用它来创建一个可与原始数据合并的 DataFrame。
† 由于 \w+
是匹配任何字母、数字或下划线的贪婪标记,因此最好使用 [a-zA-Z]+
代替,它只会匹配字母。