Python 将字符串更改为包含条件的列

Python 将字符串更改为包含条件的列,python,regex,pandas,Python,Regex,Pandas,我有一个数据帧,比如 Col1 Col2 G1 element.1:410022-411732(+):element_element G1 element.2:678-10098(-):element_element G1 element.4:6868-9899(-):element_element G1 element.1:789-1222(+):element_element G2 element.2:890-1220(-):element_element G3 element.1:12-6

我有一个数据帧,比如

Col1 Col2
G1 element.1:410022-411732(+):element_element
G1 element.2:678-10098(-):element_element
G1 element.4:6868-9899(-):element_element
G1 element.1:789-1222(+):element_element
G2 element.2:890-1220(-):element_element
G3 element.1:12-678(+):element_element
G3 element.1:1298-3000(-):element_element
G4 element.8:23222-98889(+):element_element
G5 element.1:1233-7789(-):element_element
G5 element.9:23333-23390(+):element_element
正如您所见,Col2中的值具有特定的结构:

元素内容是可变的:
element.9
:23333-23390(+):
元素
元素

但是结构总是一样的:element.9
23333
-
23390
+
):
element
element

您总是有两个数字由
-
:element分隔。9:
23333-23390
(+):element\u element

当符号为=
)时,我想通过从第一个数字1中减去来更改Col2中的值

例如
element.1:1233-7789(-):element\u element

变成

element.1:1232-7789(-):element_element
因为
1233-1=1232

对于all示例,我应该获得一个新的df,例如:

Col1 Col2
G1 element.1:410022-411732(+):element_element
G1 element.2:677-10098(-):element_element
G1 element.4:6867-9899(-):element_element
G1 element.1:789-1222(+):element_element
G2 element.2:889-1220(-):element_element
G3 element.1:12-678(+):element_element
G3 element.1:1297-3000(-):element_element
G4 element.8:23222-98889(+):element_element
G5 element.1:1232-7789(-):element_element
G5 element.9:23333-23390(+):element_element
谢谢你的帮助

我想一个办法应该是使用str.split?但我不知道如何处理它,因为在这里我必须
将Col2
拆分为
3 Col2bis列
s:

Col1 Col2.1     Col2.2 Col2.3 
G1   element.9: 23333  -23390(+):element_element
然后是Col2.2

df['Col2.2']=df['Col2.2']-1
然后再次将3根柱子粘合在一起

df["Col2"] = df["Col2.1"] + df["Col2.2"] + df["Col2.3"]
因此,我使用正则表达式从
Col2
字符串中获取所有数字,选择中间值,减去一,然后将该值替换回列

def func(x_):
    a = re.findall(r'\d+', x_)[1]
    return x_.replace(a, str(int(a)-1))

# Sample frame
x = StringIO("""Col1,Col2
G1,element.1:410022-411732(+):element_element
G1,element.2:678-10098(-):element_element
G1,element.4:6868-9899(-):element_element
G1,element.1:789-1222(+):element_element
G2,element.2:890-1220(-):element_element
G3,element.1:12-678(+):element_element
G3,element.1:1298-3000(-):element_element
G4,element.8:23222-98889(+):element_element
G5,element.1:1233-7789(-):element_element
G5,element.9:23333-23390(+):element_element
""")


df = pd.read_csv(x, sep=',')
df['Col2'] = df['Col2'].apply(lambda x: func(x))

print(df)
输出:

  Col1                                        Col2
0   G1  element.1:410021-411732(+):element_element
1   G1      element.2:677-10098(-):element_element
2   G1      element.4:6867-9899(-):element_element
3   G1       element.1:788-1222(+):element_element
4   G2       element.2:889-1220(-):element_element
5   G3         element.1:11-678(+):element_element
6   G3      element.1:1297-3000(-):element_element
7   G4    element.8:23221-98889(+):element_element
8   G5      element.1:1232-7789(-):element_element
9   G5    element.9:23332-23390(+):element_element

检查这是否对您有效:想法是创建一个模式,进行减法运算,并用pandas的方法替换字符串

pat=r“(?P.*\d:)(?P\d+(-P.*\(\)”
repl=lambda m:f'{m.group(“start”)}{int(m.group(“num”)-1}{m.group(“end”)}'
df.Col2=df.Col2.str.replace(pat,repl)
df
Col1 Col2
0 G1元件。1:410022-411732(+):元件
1 G1元件。2:677-10098(-):元件
2 G1元件。4:6867-9899(-):元件
3 G1元件。1:789-1222(+):元件
4 G2元件。2:889-1220(-):元件
5 G3元件。1:12-678(+):元件
6 G3元件。1:1297-3000(-):元件
7 G4元件。8:23222-98889(+):元件
8 G5元件。1:1232-7789(-):元件
9 G5元件。9:23333-23390(+):元件
具有矢量化操作的“pandasic”解决方案:

import pandas as pd
from io import StringIO

data = StringIO("""Col1,Col2
G1,element.1:410022-411732(+):element_element
G1,element.2:678-10098(-):element_element
G1,element.4:6868-9899(-):element_element
G1,element.1:789-1222(+):element_element
G2,element.2:890-1220(-):element_element
G3,element.1:12-678(+):element_element
G3,element.1:1298-3000(-):element_element
G4,element.8:23222-98889(+):element_element
G5,element.1:1233-7789(-):element_element
G5,element.9:23333-23390(+):element_element
""")

df = pd.read_csv(data, sep=',')

extracted = df["Col2"].str.extract(r"([^:]*:)(?P<num>\d+)([^(]*\()(?P<flag>[+-])(\).*)")

extracted["num"] = pd.to_numeric(extracted["num"])
extracted.loc[extracted["flag"] == "-", "num"] -= 1
extracted["num"] = extracted["num"].astype(str)

df["Col2"] = extracted[0].str.cat(extracted.iloc[:, 1:])
将熊猫作为pd导入
从io导入StringIO
data=StringIO(““”Col1,Col2
G1,元件1:410022-411732(+):元件
G1,元件2:678-10098(-):元件
G1,元素4:6868-9899(-):元素
G1,元件1:789-1222(+):元件
G2,元素2:890-1220(-):元素
G3,元件1:12-678(+):元件
G3,元件1:1298-3000(-):元件
G4,元素8:23222-98889(+):元素
G5,元素1:1233-7789(-):元素
G5,元素9:23333-23390(+):元素
""")
df=pd.read_csv(数据,sep=',')
extracted=df[“Col2”].str.extract(r)([^::]*:)(?P\d+)([^(]*\()(?P[+-])(\)*)
提取的[“num”]=pd.to_numeric(提取的[“num”])
extracted.loc[extracted[“flag”]==“-”,“num”]-=1
提取的[“num”]=提取的[“num”].aType(str)
df[“Col2”]=extracted[0].str.cat(extracted.iloc[:,1:)

如果您在自己解决此问题时遇到了特定问题,您可以在此处提问。您能更具体地说明问题是什么吗?请参阅。@AMC我猜他的问题已经完成,有4个不同的用户试图回答。因此没有必要投否决票,只是我的意见。@CavinDsouza这并不能说明问题已经解决按照标准,有很多糟糕的问题得到了回答。总是-1吗?我以为OP想减去第一个值?@displayname我也这么认为,但当我检查他的样本输出时,似乎所有值都比原始值少一个,尽管有些保持不变。对于大数据帧来说有点慢。@MichaelButscher,嗯,但我不能不要想一个矢量化的方法来实现这一点,比如split和/或regex似乎是必要的。我只在字符串中有
(-)
时才对第一个值执行-1,而不是
(+)
谢谢,但是
元素
部分可以有它可以随时更改的任何内容。所以使用“el”来检测“el”是行不通的是组名,与内容无关。只要内容与组“el”的regex模式匹配,这里就是我在col2
UCOL01000782.1:1094-1750(-)中的真实df示例:Canis_lube
当我尝试代码时,没有任何变化…啊,我会…给我一个moment@CavinDsouza你知道否决票是网站中完全正常的一部分,对吧?谢谢,但我只得到nan值:
df[“Col2”].str.extract(r)([^:]*:)(?P\d+([^(]*\()(?P[+-])(\)*)0 num 2 flag 4 0 NaN NaN NaN NaN 1 NaN NaN NaN NaN NaN NaN NaN NaN 2 NaN NaN NaN NaN NaN NaN 3 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 4 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaNur数据(注意这里的列是用逗号分隔的)。
pat = r"(?P<start>.*\d:)(?P<num>\d+)(?P<end>.*\(-\))"
repl = lambda m: f'{m.group("start")}{int(m.group("num"))-1}{m.group("end")}'
df.Col2 = df.Col2.str.replace(pat,repl)
df

    Col1    Col2
0   G1  element.1:410022-411732(+):element_element
1   G1  element.2:677-10098(-):element_element
2   G1  element.4:6867-9899(-):element_element
3   G1  element.1:789-1222(+):element_element
4   G2  element.2:889-1220(-):element_element
5   G3  element.1:12-678(+):element_element
6   G3  element.1:1297-3000(-):element_element
7   G4  element.8:23222-98889(+):element_element
8   G5  element.1:1232-7789(-):element_element
9   G5  element.9:23333-23390(+):element_element
import pandas as pd
from io import StringIO

data = StringIO("""Col1,Col2
G1,element.1:410022-411732(+):element_element
G1,element.2:678-10098(-):element_element
G1,element.4:6868-9899(-):element_element
G1,element.1:789-1222(+):element_element
G2,element.2:890-1220(-):element_element
G3,element.1:12-678(+):element_element
G3,element.1:1298-3000(-):element_element
G4,element.8:23222-98889(+):element_element
G5,element.1:1233-7789(-):element_element
G5,element.9:23333-23390(+):element_element
""")

df = pd.read_csv(data, sep=',')

extracted = df["Col2"].str.extract(r"([^:]*:)(?P<num>\d+)([^(]*\()(?P<flag>[+-])(\).*)")

extracted["num"] = pd.to_numeric(extracted["num"])
extracted.loc[extracted["flag"] == "-", "num"] -= 1
extracted["num"] = extracted["num"].astype(str)

df["Col2"] = extracted[0].str.cat(extracted.iloc[:, 1:])