Python 熊猫:借助字典将变量子字符串从A列插入B列

Python 熊猫:借助字典将变量子字符串从A列插入B列,python,regex,string,pandas,Python,Regex,String,Pandas,我有一个pandasdataframe: df = pd.DataFrame(["LONG AAPL 2X CBZ","SHORT GOOG 10X VON"], columns=["Name"]) 我想在名称列中标识“AAPL”,通过字典“AAPL”:“Apple”,然后将其插入新列说明中的字符串中 期望输出: Name Description "LONG AAPL 2X CBZ" "Tracks Apple with 2X leverage."

我有一个
pandas
dataframe:

df = pd.DataFrame(["LONG AAPL 2X CBZ","SHORT GOOG 10X VON"], columns=["Name"])
我想在
名称
列中标识
“AAPL”
,通过字典
“AAPL”:“Apple”
,然后将其插入新列
说明
中的字符串中

期望输出:

Name                   Description
"LONG AAPL 2X CBZ"     "Tracks Apple with 2X leverage."
"SHORT GOOG 10X VON"   "Tracks Google with -10X leverage."
我遇到的问题是在另一个字符串中输入一个变量子字符串,如
“使用Y杠杆跟踪X。”

如果我不必这样做,只需从
name
提取到
description
即可:

df["Description"] = df["Name"].str.extract(r"\s(\S+)\s").map({"AAPL":"Apple", "GOOG":"Google"})
或者提取杠杆:

df["Description"] = df["Name"].str.extract(r"(\d+X)")
如果可能的话,我想使用
regex
来提取变量,因为实际上我会做一些更详细的regex,例如检索不同格式的乘法器,例如
X2
2x
等等

注意:我可能需要设置另一列来通知杠杆是正还是负,并使用该列来决定是否将
“-”
作为
-10X杠杆追加到乘数前面。

df["direction"] = df["name"].map(lambda x: "Long" if "LONG" in x else "Short" if "SHORT " in x else "Long")

Name                   Direction      Description
"LONG AAPL 2X CBZ"     "Long"         "Tracks Apple with 2X leverage."
"SHORT GOOG 10X VON"   "Short"        "Tracks Google with -10X leverage."

您可以定义一个显式函数来应用于整个
Name
系列

df = pd.DataFrame(["LONG AAPL 2X CBZ","SHORT GOOG 10X VON"], columns=["Name"])

dmap = {"AAPL":"Apple", "GOOG":"Google"}
signmap = {"LONG": "", "SHORT": "-"}

def f(strseries):
    company = strseries.str.extract(r"\s(\S+)\s").map(dmap)
    leverage = strseries.str.extract(r"(\d+X)")
    sign = strseries.str.extract(r"(\S+)\s").map(signmap)
    return "Tracks " + company + " with " + sign + leverage + " leverage."

df['Description'] = f(df['Name'])
编辑:一次完成正则表达式提取大约可以提高2倍的速度,但要牺牲一些可读性

def f2(strseries):
    sub_df = strseries.str.extract('(?P<sign>\S+)\s(?P<company>\S+)\s(?P<leverage>\d+X)')
    return "Tracks " + sub_df.company.map(dmap) + " with " + sub_df.sign.map(signmap) + sub_df.leverage + " leverage."

df['Description'] = f2(df['Name'])
def f2(标准系列):
sub_df=strseries.str.extract(“(?P\S+)\S(?P\S+)\S(?P\d+X)”
返回带有“+sub_-df.sign.map(signmap)+sub_-df.leverage+”的“Tracks”+sub_-df.company.map(dmap)+”
df['Description']=f2(df['Name'])

因为我们只关心前两个子字符串和后两个子字符串:

df = pd.DataFrame(["LONG AAPL 2X CBZ", "SHORT GOOG 10X VON", "BULL AXP UN X3 VON","LONG AXP X3 VON"], columns=["Name"])

maps = {"AAPL": "Apple", "GOOG": "Google"}
signs = {"SHORT": "-"}

def split(i):
    spl = i.split()
    a, b, c = spl[0], spl[1], spl[-2]
    val = maps.get(b, b) # if name is not to be replaced keep original
    return "Tracks  {} with {}{} leverage".format(val, signs.get(a, ""), c)

df["Description"]  = df["Name"].map(split)
输出:

                 Name                        Description
0    LONG AAPL 2X CBZ     Tracks  Apple with 2X leverage
1  SHORT GOOG 10X VON  Tracks  Google with -10X leverage
2  BULL AXP UN X3 VON       Tracks  AXP with X3 leverage
3     LONG AXP X3 VON       Tracks  AXP with X3 leverage
仅拆分比使用正则表达式更有效:

In [33]: df2 = pd.concat([df]*10000)
In [34]: timeit  df2["Name"].map(split)
10 loops, best of 3: 57.5 ms per loop

In [35]: timeit f2(df2['Name'])
10 loops, best of 3: 168 ms per loop

如果您想添加更多的单词来替换,只需将它们添加到地图中,并使用符号来替换。

是否应该是
“LONG AAPL 2X CBZ”
?谢谢,更正了数据框。这不能正确处理问题中描述的杠杆符号。@abeboparebop,我错过了那一部分,但这对我来说是微不足道的implement@PadraicCunningham如果中间有更多的文本怎么办?对于
BULL AXP UN X3 VON
我得到:
ValueError:太多的值无法解包
。不幸的是,这会有很大的变化,这使得按空格拆分很困难。@Winterflags,我们可以使用带有findall的正则表达式,我将进行编辑,当您没有带有AAPL或GOOG的行时,您希望发生什么?然后我们可以再次拆分!这个名字总是一个单词吗?我想使用这个解决方案,因为正则表达式对于许多不同的情况来说更加健壮。但是,如果在
dmap
中没有匹配项,我如何让它将
\s(\s+)\s
写为
公司
?类似于:
val=maps.get(b,b);返回“使用{}{}杠杆跟踪{}”。格式(val,signs.get(a,“”),c)