基于dataframe python中的子字符串提取字符串的部分

2024-09-29 17:19:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图提取一些NBA数据,但我的数据框有一个列,其中所有统计数据都在一个字符串中,由统计列中的空格分隔,如图所示:例如29pt 15rb 3as 1bl…等。我想提取每个统计数据的值,这样我就有了一列记录分数、篮板、助攻、盖帽等的数据。我遇到的问题是有些行可能不包含所有统计数据。例如,如果一名球员没有获得任何助攻,他们在统计栏中的值可能如下所示:14pt 3rb 2bl。我在提取每个统计数据所需的值时遇到困难,尤其是当该玩家不存在统计数据时。我曾尝试拆分字符串,以便将其值放入一个列表中,这是很有希望的,但我仍然无法找出如何获取每个统计值(如果该播放器存在该统计值)。任何建议、想法或指导都将不胜感激。谢谢

山猫


Tags: 数据字符串列表记录玩家播放器分数建议
2条回答

我们可以使用^{}来提取值(regex解释的here),然后将其转换为dict,并将其转换回一个数据帧,该数据帧将统计信息作为列标签和值

>>> 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

然后可以将此数据帧合并到索引上匹配的原始数据帧上


s.str.findall(r"(\d+)(\w+)")

此行应用regex r"(\d+)(\w+)",它定义了两个捕获组(括号())。第一个捕获组查找数字(\d+),第二个捕获组查找单词字符(\w+,相当于[a-zA-Z0-9_])。使用findall返回元组列表,例如

"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转换成一个dict列表,我们可以使用它创建一个可与原始数据合并的数据帧


†因为\w+是一个贪婪的标记,它匹配任何字母、数字或下划线,所以最好使用[a-zA-Z]+,它只匹配字母

也许是这样的

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

相关问题 更多 >

    热门问题