【问题标题】:Pandas: extract and select data from columns using a patternPandas:使用模式从列中提取和选择数据
【发布时间】:2013-04-30 00:19:42
【问题描述】:

我的数据包含类似这样的结构(减少到2个元素,但有几十个):

Variable        elem_1_pre    elem_1_post   elem_2_pre    elem_2_post
Observation1    present       absent        absent        present
Observation2    absent        present       present       absent

最终目标是选择pre 中存在但post 中不存在的观察值(可能还有相关的列名),反之亦然。

换句话说,像(伪代码)这样​​的操作

("present" in *_pre and "absent" in *_post) or
("present" in *_post and "absent" in *_pre)

我想groupby 可以用于此。熊猫可以做到这一点吗?

【问题讨论】:

    标签: python group-by pandas


    【解决方案1】:

    如果您的 DataFrame 中的值正是字符串 'present''absent',那么您可以使用

    将字符串值转换为布尔值
    In [17]: df.values == 'present'
    Out[17]: 
    array([[ True, False, False,  True],
           [False,  True,  True, False]], dtype=bool)
    

    获得布尔值后,您可以使用 NumPy XOR 逻辑运算符 ^ 将两列组合成所需的值:

    import pandas as pd
    df = pd.DataFrame(['present absent absent present'.split(),
                       'absent present present absent'.split()],
                      columns='elem_1_pre elem_1_post elem_2_pre elem_2_post'.split(),
                      index='Observation1 Observation2'.split(),)
    df = pd.DataFrame(df.values == 'present',
                      columns=df.columns,
                      index=df.index)
    print(df)
    #              elem_1_pre elem_1_post elem_2_pre elem_2_post
    # Observation1       True       False      False        True
    # Observation2      False        True       True       False
    
    for i in range(1,3):
        elem = ['elem_{i}_{s}'.format(i=i, s=suf) for suf in ('pre', 'post')]
        change = 'elem_{i}_change'.format(i=i)
        df[change] = df[elem[0]] ^ df[elem[1]]
    print(df.ix[:, 'elem_1_change elem_2_change'.split()])
    

    产量

                 elem_1_change elem_2_change
    Observation1          True          True
    Observation2          True          True
    

    【讨论】:

    • 它们正是那些,因为我构建了源 DataaFrame,所以我会试一试。谢谢
    【解决方案2】:

    您想知道这里是否可以使用groupby,所以我会提到它是如何使用的。简短的版本,虽然为了清楚起见我可能会写成两行:

    (df == 'present').groupby(lambda x: x.rsplit("_", 1)[0], axis=1).sum() == 1
    

    首先,我们可以从一个示例数据框开始,对@unutbu 的赞美(注意:这与您的不同,因此输出并非全部为真):

    >>> import pandas as pd
    >>> df = pd.DataFrame(['present absent absent absent'.split(),
                       'present present present absent'.split()],
                      columns='elem_1_pre elem_1_post elem_2_pre elem_2_post'.split(),
                      index='Observation1 Observation2'.split(),)
    >>> df
                 elem_1_pre elem_1_post elem_2_pre elem_2_post
    Observation1    present      absent     absent      absent
    Observation2    present     present    present      absent
    

    我们可以确定其中哪些是present

    >>> p = df == "present"
    >>> p
                 elem_1_pre elem_1_post elem_2_pre elem_2_post
    Observation1       True       False      False       False
    Observation2       True        True       True       False
    

    然后,我们真正想做的是将列分组到“elem_1”位中。您可以使用字符串方法或正则表达式,甚至可以使用已排序的索引。我喜欢使用字符串方法,所以我们将列名拆分为右侧的第一个_。要对列进行分组,我们使用axis=1

    >>> for k, g in p.groupby(lambda x: x.rsplit("_", 1)[0], axis=1):
        print 'group key:', k
        print g
    ...     
    group key: elem_1
                 elem_1_pre elem_1_post
    Observation1       True       False
    Observation2       True        True
    group key: elem_2
                 elem_2_pre elem_2_post
    Observation1      False       False
    Observation2       True       False
    

    我们想连续计算 True 值,看看是否只有一个。 True ~ 1 和 False ~ 0,所以我们可以使用sum

    >>> p.groupby(lambda x: x.rsplit("_", 1)[0], axis=1).sum()
                  elem_1  elem_2
    Observation1       1       0
    Observation2       2       1
    

    然后

    >>> p.groupby(lambda x: x.rsplit("_", 1)[0], axis=1).sum() == 1
                 elem_1 elem_2
    Observation1   True  False
    Observation2  False   True
    

    或者,把它们放在一起:

    >>> grouped = (df == "present").groupby(lambda x: x.rsplit("_", 1)[0], axis=1)
    >>> answer = grouped.sum() == 1
    >>> answer
                 elem_1 elem_2
    Observation1   True  False
    Observation2  False   True
    

    【讨论】:

      猜你喜欢
      • 2021-09-21
      • 1970-01-01
      • 2021-01-07
      • 2018-09-17
      • 2020-06-09
      • 2022-01-03
      • 2019-12-02
      相关资源
      最近更新 更多