检查是否在熊猫数据框中找到组ID或元素

时间:2019-12-02 16:10:21

标签: pandas dataframe pandas-groupby

data = {

    'org_id' :[4,73,6,77,21,36,40,22,21,30,31],
    'flag': [['4', '73'],['73'],['6', '77'],['77'],['21'],['36', '36'],['40'],['22', '41'],['21'],['22', '30'],['31', '31']],
    'r_id' : [4,4,6,6,20,20,20,22,28,28,28]


    }

df = pd.DataFrame.from_dict(data)
df

所需的数据帧如下所示,

data = {

    'org_id' :[4,73,6,77,21,36,40,22,21,30,31],
    'flag': [['4', '73'],['73'],['6', '77'],['77'],['21'],['36', '36'],['40'],['22', '41'],['21'],['22', '30'],['31', '31']],
    'r_id' : [4,4,6,6,20,20,20,22,28,28,28],
    'is_foundin_org_id': ['yes','yes','yes','yes','NO','NO','NO','yes','NO','NO','NO']

    }

df2 = pd.DataFrame.from_dict(data)
df2

输出数据帧

Out[115]: 
    org_id      flag  r_id is_foundin_org_id
0        4   [4, 73]     4               yes
1       73      [73]     4               yes
2        6   [6, 77]     6               yes
3       77      [77]     6               yes
4       21      [21]    20                NO
5       36  [36, 36]    20                NO
6       40      [40]    20                NO
7       22  [22, 41]    22               yes
8       21      [21]    28                NO
9       30  [22, 30]    28                NO
10      31  [31, 31]    28                NO

需要在按r_id分组后识别r_id的分组行中是否存在r_id,例如。当我在org_id的某一行中找到按4分组时,因此我将第4组标记为是,类似地,在org_id列中未找到20,因此将所有20s组标记为否。谢谢。

3 个答案:

答案 0 :(得分:3)

IIUC,

df['is_found'] = np.where(df['org_id'].eq(df['r_id']) # check if the ids are equal
                              .groupby(df['r_id'])    # group by r_id
                              .transform('any'),      # if True occurs within the groups
                          'yes', 'no')

输出:

    org_id      flag  r_id is_found
0        4   [4, 73]     4      yes
1       73      [73]     4      yes
2        6   [6, 77]     6      yes
3       77      [77]     6      yes
4       21      [21]    20       no
5       36  [36, 36]    20       no
6       40      [40]    20       no
7       22  [22, 41]    22      yes
8       21      [21]    28       no
9       30  [22, 30]    28       no
10      31  [31, 31]    28       no

答案 1 :(得分:3)

尝试一下

d = {True: 'Yes', False: 'No'}
df['is_foundin_org_id'] = (df.org_id.eq(df.r_id).groupby(df.r_id)
                             .transform('max').map(d))

Out[1549]:
    org_id      flag  r_id is_foundin_org_id
0   4       [4, 73]   4     Yes
1   73      [73]      4     Yes
2   6       [6, 77]   6     Yes
3   77      [77]      6     Yes
4   21      [21]      20    No
5   36      [36, 36]  20    No
6   40      [40]      20    No
7   22      [22, 41]  22    Yes
8   21      [21]      28    No
9   30      [22, 30]  28    No
10  31      [31, 31]  28    No

答案 2 :(得分:1)

Numpypandas.factorize

这似乎令人费解。但是我正在使用Numpy并将所有内容保留为 O(n)

获取数组,因为我将多次使用它们

a = df.r_id.to_numpy()
b = df.org_id.to_numpy()

因子化可以用从零开始的整数来标识每个唯一值。 pandas.factorize将返回(factorized_integer_representation, unique_values)的元组。分解的优点在于,我可以使用这些整数作为唯一值数组中的位置来重现原始数组。即使用下面的r[i]ri

我还可以将numpy.unique与参数return_inverse一起使用来获取相同的数组,但是 pandas.factorize不会对唯一值进行排序,是 O(log(n))的订单,我们可以通过不使用来保存该订单。对于更大的数据,pandas.factorize是赢家。

我将创建一个保存数组,该数组将容纳关于每个唯一值是否满足我们的 any 条件的布尔值。 numpy.logical_or.at是我们用来查看来自a == b的任何值是否在True中指定索引内的i的功能。

我将在下面的代码后面进行演示。

i, r = pd.factorize(a)
o = np.zeros(len(r), bool)
np.logical_or.at(o, i, a == b)

df.assign(is_found=np.where(o, 'Yes', 'No')[i])

    org_id      flag  r_id is_found
0        4   [4, 73]     4      Yes
1       73      [73]     4      Yes
2        6   [6, 77]     6      Yes
3       77      [77]     6      Yes
4       21      [21]    20       No
5       36  [36, 36]    20       No
6       40      [40]    20       No
7       22  [22, 41]    22      Yes
8       21      [21]    28       No
9       30  [22, 30]    28       No
10      31  [31, 31]    28       No

详细信息

a == b

array([True, False, True, False, False, False, False, True, False, False, False])

r是唯一值

r

array([ 4,  6, 20, 22, 28])

i是索引

i

array([0, 0, 1, 1, 2, 2, 2, 3, 4, 4, 4])

所以r[i]复制了a

r[i]

array([ 4,  4,  6,  6, 20, 20, 20, 22, 28, 28, 28])

现在,我们从全为False的基数组o开始,每个唯一值一个

array([False, False, False, False, False])

对于i中的每个位置,我们检查a == b中的对应值是否为True

#  i, a == b ->  0,  True <4 == 4>
#                0, False <4 != 73>
#                     ↓    1,  True <6 == 6>
#                     ↓    1, False <6 != 77>
#                     ↓         ↓    2, False <20 != 21>
#                     ↓         ↓    2, False <20 != 36>
#                     ↓         ↓    2, False <20 != 40>
#                     ↓         ↓         ↓    3,  True <22 == 22>
#                     ↓         ↓         ↓         ↓    4, False <28 != 21>
#                     ↓         ↓         ↓         ↓    4, False <28 != 30>
#                     ↓         ↓         ↓         ↓    4, False <28 != 31>
#  At least 1 True    ↓         ↓         ↓         ↓         ↓
#  o         -> [    True,     True,    False,     True,    False]

交换Yes | No而不是True | False

#  o                         -> [    True,     True,    False,     True,    False]
#  np.where(o, 'Yes', 'No')  -> [   'Yes',    'Yes',     'No',    'Yes',     'No']

并用i对其进行切片,以生成与原始长度相同的数组,并为唯一值数组中的每个对应值提供适当的值。

np.where(o, 'Yes', 'No')[i]

['Yes', 'Yes', 'Yes', 'Yes', 'No', 'No', 'No', 'Yes', 'No', 'No', 'No']