Pandas 检查是否在数据框中的列列表中找到组id或元素
所需数据帧如下所示Pandas 检查是否在数据框中的列列表中找到组id或元素,pandas,dataframe,pandas-groupby,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
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
在按r_id分组后,需要确定r_id是否存在于r_id的分组行中,例如,当在org_id的一行中发现I group by 4时,因此我为组4标记yes,类似地,在org_id列中未找到20,因此我为所有20岁组标记No。谢谢你。IIUC
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
输出:
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
Numpy
和pandas.factorize
这似乎很复杂。但我使用的是Numpy
并将所有内容O(n)
获取数组,因为我将多次使用它们
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
分解某物用一个以零开始的整数标识每个唯一值pandas.factorize
将返回的元组(factorized\u integer\u表示,唯一的\u值)
。因式分解的好处在于,我可以使用这些整数作为唯一值数组中的位置来重现原始数组。即使用下面的r
和i
我也可以使用numpy.unique
和参数return\u inverse
来获得相同的数组,但是pandas.factorize
不会对唯一值进行排序,这是一个O(log(n))的顺序,我们可以通过不使用它来保存。对于较大的数据,pandas.factorize
是赢家
我将创建一个保留数组,该数组将根据每个唯一值是否满足任何条件来容纳布尔值numpy.logical_或.at
是我们用来查看a==b
中的任何值是否True
在i
中的指定索引内
我将在下面的代码之后演示
a = df.r_id.to_numpy()
b = df.org_id.to_numpy()
细节
r
是唯一的值
a == b
array([True, False, True, False, False, False, False, True, False, False, False])
i
是索引
r
array([ 4, 6, 20, 22, 28])
所以
r[i]
复制a
i
array([0, 0, 1, 1, 2, 2, 2, 3, 4, 4, 4])
现在我们从一个包含所有False的基本数组
o
开始,每个惟一值对应一个
r[i]
array([ 4, 4, 6, 6, 20, 20, 20, 22, 28, 28, 28])
对于i
中的每个位置,我们检查a==b
中的对应值是否为True
array([False, False, False, False, False])
然后使用i
对其进行切片,以生成一个与原始数组长度相同的数组,并为唯一值数组中的每个对应值提供适当的值
# o -> [ True, True, False, True, False]
# np.where(o, 'Yes', 'No') -> [ 'Yes', 'Yes', 'No', 'Yes', 'No']
标记的用途是什么,如果与问题无关,您可以删除它吗?我想知道第一个
r\u id
是否可能是73
,而不是4
@ragaelc,IIUC,73可以是well@rafaelc在groupbyr\u id
之后的每个操作,因此该案例将产生两个no
?@QuangHoang Yea!我的解释和你一样,但是这个flag
专栏就像你的numpy解决方案一样把我甩了:1+1Thx@AndyL。更新了更多细节。哇,很好的详细解释。我把它标记为我的最爱。竖起大拇指!
# 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]
# o -> [ True, True, False, True, False]
# np.where(o, 'Yes', 'No') -> [ 'Yes', 'Yes', 'No', 'Yes', 'No']
np.where(o, 'Yes', 'No')[i]
['Yes', 'Yes', 'Yes', 'Yes', 'No', 'No', 'No', 'Yes', 'No', 'No', 'No']