【问题标题】:check if the group id or element is found the column list in pandas data frame检查是否在 pandas 数据框中的列列表中找到组 ID 或元素
【发布时间】:2019-12-03 02:13:16
【问题描述】:
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 组标记为否。谢谢你。

【问题讨论】:

  • flag是干什么用的,如果和问题无关的话可以去掉

标签: pandas dataframe pandas-groupby


【解决方案1】:

试试这个

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】:

    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
    

    【讨论】:

    • 我想知道第一个r_id是否有可能是73而不是4
    • @ragaelc, IIUC, 73 也可以是一个组
    • @rafaelc 每个 OP 的 在 groupby r_id 之后,所以这种情况会产生两个 no?
    • @QuangHoang 是的!我和你一样解释过,但是这个flag 专栏让我失望了哈哈
    【解决方案3】:

    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 中的任何值是否在i 中指定索引内的True 的函数。

    我会在下面的代码之后演示。

    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']
    

    【讨论】:

    • 我喜欢你的 numpy 解决方案 :) +1
    • 谢谢@AndyL。更新了更多细节。
    • 哇,好详细的解释。我把它标记为我的最爱。竖起大拇指!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-05
    • 2021-08-19
    • 2021-06-26
    • 2021-07-10
    • 2019-07-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多