根据Pandas DataFrame中的其他列值在列之间移动行值

时间:2013-04-14 09:09:07

标签: python pandas

我有一个大熊猫数据框,其中列出了有机体名称及其抗生素敏感性。我希望根据以下规则将所有生物合并到下面的DataFrame中的一列中。

  1. 如果ORG1 == A,则什么都不做;

  2. 如果ORG1!= A且ORG2 == A,请将ORG2值移至ORG1列

  3. 如果ORG1!= A且ORG3 == A,请将ORG3值移至ORG1列

  4. 如果满足条件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
    

1 个答案:

答案 0 :(得分:2)

我们可以选择ORG1 != AORG2 == 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值,我们还需要映射{{ 1}} s为False,因此我们使用NaN


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*中的值。我不确定你想赢得哪个值。在上面的代码中, last 列获胜,即AS10*