Python 熊猫:使用模式从列中提取和选择数据

Python 熊猫:使用模式从列中提取和选择数据,python,group-by,pandas,Python,Group By,Pandas,我的数据包含与此类似的结构(减少为2个元素,但有十个元素): 最终目标是选择在pre中出现但在post中不存在的观察结果(以及可能的相关列名),反之亦然 换句话说,类似(伪代码)的操作 我想,groupby可以用于此。pandas是否可以这样做?如果数据帧中的值正好是字符串'present'和'empture',则可以使用 In [17]: df.values == 'present' Out[17]: array([[ True, False, False, True], [

我的数据包含与此类似的结构(减少为2个元素,但有十个元素):

最终目标是选择在
pre
中出现但在
post
中不存在的观察结果(以及可能的相关列名),反之亦然

换句话说,类似(伪代码)的操作


我想,
groupby
可以用于此。pandas是否可以这样做?

如果数据帧中的值正好是字符串
'present'
'empture'
,则可以使用

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

您想知道这里是否可以使用
groupby
,因此我将介绍如何使用它。简短的版本,不过为了清晰起见,我可能会用两行文字来写:

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

首先,我们可以从一个示例数据帧开始,称赞@unutbu(注意:这与您的不同,因此输出不完全正确):

我们可以确定哪些是
存在的

>>> 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”位。您可以使用字符串方法或正则表达式,甚至是按顺序排列的索引。我喜欢使用字符串方法,因此我们将按右边的第一个
\uuu
拆分列名。要在列上分组,我们使用轴=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~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

它们正是这些,因为我构建了源DataaFrame,所以我将试一试。谢谢
>>> 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