2

我的数据包含与此类似的结构(减少到 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可以用于这个。熊猫可以做到这一点吗?

4

2 回答 2

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
于 2013-05-06T12:09:55.950 回答
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
于 2013-05-06T09:34:01.723 回答