我有一个熊猫数据框,上面列出了生物名称及其对抗生素的敏感性.我希望根据以下规则将所有生物整合到下面的数据框架中的一栏中.
>如果ORG1 == A,则什么都不做;
>如果ORG1!= A和ORG2 == A,则将ORG2值移至ORG1列
>如果ORG1!= A和ORG3 == A,请将ORG3值移至ORG1列
如果满足条件2,并将ORG2的值移至ORG1列,则还将AS20 *中的列值移至AS10 *中.
同样,如果满足条件3,并将ORG3值移动到ORG1列,则也将AS30 *中的列值移动到AS10 *中.
我自己根据上述规则编写了一个函数来进行尝试,但由于以下原因,成功有限:
If ORG2 == A:
return ORG1.map(ORG2)
当我尝试顺序映射AS201时我迷路了-> < AS101,AS202-> < AS102,AS203-> AS103等根据条件而定.
我的另一个问题是生物名称不是单个字母,也不是漂亮的字母.示例中的A等效于我的数据集中的re.match(‘aureus’).
另外,每个ORG列都有20个AS列,并超过150,000条记录,因此我希望使其能够推广用于任何数量的抗生素敏感性结果.
我为此付出了一些努力,因此朝正确方向推几把确实会有所帮助.
提前致谢.
Index ORG1 ORG2 ORG3 AB1 AS101 AS201 AS301 AB2 AS102 AS202 AS302 1 A NaN NaN pen S NaN NaN dfluc S NaN NaN 2 A B C pen R S S dfluc S R S 3 B A B pen S S R dfluc S S R 4 A NaN NaN pen R NaN NaN dfluc S NaN NaN 5 A NaN NaN pen R NaN NaN dfluc S NaN NaN 6 C A A pen S R R dfluc R S R 7 B NaN A pen R NaN S dfluc S NaN S 8 A B A pen R R R dfluc R R R 9 A NaN NaN pen R NaN NaN dfluc S NaN NaN
解决方法:
我们可以选择ORG1!= A和ORG2 == A的行
mask = (df['ORG1'] != 'A')&(df[orgi] == 'A')
mask是一个布尔系列.要将值从ORG2复制到ORG1,我们可以使用
df['ORG1'][mask] = df['ORG2'][mask]
或者,因为我们知道右边的值为A,所以我们可以使用
df['ORG1'][mask] = 'A'
复制AS列可以类似地完成.
我们可以找到行的列值包含诸如“ aureus”之类的字符串,
df[orgi].str.contains('aureus') == True
str.contains可以使用任何正则表达式模式作为其参数.
参见文档:Vectorized String Methods.
注意:通常使用df [orgi] .str.contains(‘aureus’)就足够了(不使用== True,但是由于df [orgi]可能包含NaN值,因此我们还需要将NaN映射为False,因此我们使用df [orgi] .str.contains(‘aureus’)== True.
import pandas as pd
filename = 'data.txt'
df = pd.read_table(filename, delimiter='\s+')
print(df)
# Index ORG1 ORG2 ORG3 AB1 AS101 AS201 AS301 AB2 AS102 AS202 AS302
# 0 1 A NaN NaN pen S NaN NaN dfluc S NaN NaN
# 1 2 A B C pen R S S dfluc S R S
# 2 3 B A B pen S S R dfluc S S R
# 3 4 A NaN NaN pen R NaN NaN dfluc S NaN NaN
# 4 5 A NaN NaN pen R NaN NaN dfluc S NaN NaN
# 5 6 C A A pen S R R dfluc R S R
# 6 7 B NaN A pen R NaN S dfluc S NaN S
# 7 8 A B A pen R R R dfluc R R R
# 8 9 A NaN NaN pen R NaN NaN dfluc S NaN NaN
for i in range(2,4):
orgi = 'ORG{i}'.format(i=i)
# mask = (df['ORG1'] != 'A')&(df[orgi] == 'A')
mask = (df['ORG1'].str.contains('A') == False)&(df[orgi].str.contains('A') == True)
# Move ORGi --> ORG1
df['ORG1'][mask] = df[orgi][mask]
for j in range(1,4):
# Move ASij --> AS1j
source_as = 'AS{i}{j:02d}'.format(i=i, j=j)
target_as = 'AS1{j:02d}'.format(i=i, j=j)
try:
df[target_as][mask] = df[source_as][mask]
except KeyError:
pass
print(df)
产量
Index ORG1 ORG2 ORG3 AB1 AS101 AS201 AS301 AB2 AS102 AS202 AS302
0 1 A NaN NaN pen S NaN NaN dfluc S NaN NaN
1 2 A B C pen R S S dfluc S R S
2 3 A A B pen S S R dfluc S S R
3 4 A NaN NaN pen R NaN NaN dfluc S NaN NaN
4 5 A NaN NaN pen R NaN NaN dfluc S NaN NaN
5 6 A A A pen R R R dfluc S S R
6 7 A NaN A pen S NaN S dfluc S NaN S
7 8 A B A pen R R R dfluc R R R
8 9 A NaN NaN pen R NaN NaN dfluc S NaN NaN
请注意,如果ORG2 == A和ORG3 == A,则AS20 *列和AS30 *列中的值都会争用覆盖AS10 *列中的值.我不确定您想赢得哪个价值.在上面的代码中,最后一列获胜,即AS30 *.