我有以下pandas数据框:
import pandas as pd
df = pd.DataFrame({ 'gene':["1 // foo // blabla",
"2 // bar // lalala",
"3 // qux // trilil",
"4 // woz // hohoho"], 'cell1':[5,9,1,7], 'cell2':[12,90,13,87]})
df = source_df[["gene","cell1","cell2"]]
看起来像这样:
gene cell1 cell2
0 1 // foo // blabla 5 12
1 2 // bar // lalala 9 90
2 3 // qux // trilil 1 13
3 4 // woz // hohoho 7 87
我想得到的是:
gene cell1 cell2
0 foo 5 12
1 bar 9 90
2 qux 1 13
3 woz 7 87
即按//
选择拆分字符串的第二个元素作为分隔符。
我能做的最好的就是:
df["gene"] = df["gene"].str.split(" // ")
df
Out[17]:
gene cell1 cell2
0 [1, foo, blabla] 5 12
1 [2, bar, lalala] 9 90
2 [3, qux, trilil] 1 13
3 [4, woz, hohoho] 7 87
这样做的正确方法是什么?
答案 0 :(得分:11)
使用矢量化str.split
这比在大型数据集上使用apply
要快得多:
In [13]:
df['gene'] = df['gene'].str.split('//').str[1]
df
Out[13]:
cell1 cell2 gene
0 5 12 foo
1 9 90 bar
2 1 13 qux
3 7 87 woz
答案 1 :(得分:2)
您可以使用regex
并按strip
删除第一个和最后一个空格:
df["gene"] = df["gene"].str.extract(r"\/\/([a-z ]+)\/\/")
df["gene"] = df["gene"].str.strip()
print df
gene cell1 cell2
0 foo 5 12
1 bar 9 90
2 qux 1 13
3 woz 7 87
\/\/([a-z ]+)\/\/
表示:
\/ matches the character / literally
\/ matches the character / literally
1st Capturing group ([a-z ]+)
[a-z ]+ match a single character present in the list below
Quantifier: + Between one and unlimited times, as many times as possible,
giving back as needed [greedy]
a-z a single character in the range between a and z (case sensitive)
the literal character
\/ matches the character / literally
\/ matches the character / literally
没有条带的正则表达式:
df["gene"] = df["gene"].str.extract(r"\/\/\s*([a-z ]+)\s\/\/")
/\/\/\s*([a-z ]+)\s\/\//
表示:
\/ matches the character / literally
\/ matches the character / literally
\s* match any white space character [\r\n\t\f ]
Quantifier: * Between zero and unlimited times, as many times as possible,
giving back as needed [greedy]
1st Capturing group ([a-z ]+)
[a-z ]+ match a single character present in the list below
Quantifier: + Between one and unlimited times, as many times as possible,
giving back as needed [greedy]
a-z a single character in the range between a and z (case sensitive)
the literal character
\s match any white space character [\r\n\t\f ]
\/ matches the character / literally
\/ matches the character / literally
答案 2 :(得分:1)
你非常接近,但是从结果分割中选择元素会更难以按照自己的方式进行。
以下是适用
的解决方案>>> df['gene'] = df['gene'].apply(lambda s: s.split('//')[1])
>>> df
gene cell1 cell2
0 foo 5 12
1 bar 9 90
2 qux 1 13
3 woz 7 87