如何获取 Pandas Dataframe 中由 groupby 组合的行的值列表?
How can I get a list of values for rows combined by groupby in a Pandas Dataframe?
假设我有以下数据框:
#!/usr/bin/env python
import pandas as pd
df = pd.DataFrame([(1, 2, 1),
(1, 2, 2),
(1, 2, 3),
(4, 1, 612),
(4, 1, 612),
(4, 1, 1),
(3, 2, 1),
],
columns=['groupid', 'a', 'b'],
index=['India', 'France', 'England', 'Germany', 'UK', 'USA',
'Indonesia'])
print(df)
给出:
groupid a b
India 1 2 1
France 1 2 2
England 1 2 3
Germany 4 1 612
UK 4 1 612
USA 4 1 1
Indonesia 3 2 1
第 1 步
这一步可能没有必要/与我想象的不同。我实际上只对第 2 步感兴趣,但是有了这个可以帮助我思考它并解释我想要什么。
我想按 groupid (df.groupby(df['groupid'])
) 对数据进行分组,得到这样的结果:
groupid a b
1 [2] [1, 2, 3]
4 [1] [612, 1]
3 [2] [1]
第 2 步
然后我想找到在 b 列中只有一个条目且条目等于 1
的所有组 ID。
同样,我想找到所有具有多个条目或一个条目不是 1
的组 ID。
您可以比较 set
s,然后获取 list
s 的索引值:
mask = df.groupby('groupid')['b'].apply(set) == set([1])
print (mask)
groupid
1 False
3 True
4 False
Name: b, dtype: bool
i = mask.index[mask].tolist()
print (i)
[3]
j = mask.index[~mask].tolist()
print (j)
[1, 4]
对于新列使用 map
:
df['new'] = df['groupid'].map(df.groupby('groupid')['b'].apply(set) == set([1]))
print (df)
groupid a b new
India 1 2 1 False
France 1 2 2 False
England 1 2 3 False
Germany 4 1 612 False
UK 4 1 612 False
USA 4 1 1 False
Indonesia 3 2 1 True
旧解决方案:
您可以将 transform
with nunique
用于与原始 df 大小相同的新 Series
,因此可以将其与 1
进行比较以获得唯一性,然后链接另一个条件以与 [= 进行比较21=]:
mask = (df.groupby('groupid')['b'].transform('nunique') == 1) & (df['b'] == 1)
print (mask)
India False
France False
England False
Germany False
UK False
USA False
Indonesia True
Name: b, dtype: bool
对于 list
中的唯一值:
i = df.loc[mask, 'groupid'].unique().tolist()
print (i)
[3]
j = df.loc[~mask, 'groupid'].unique().tolist()
print (j)
[1, 4]
详情:
print (df.groupby('groupid')['b'].transform('nunique'))
India 3
France 3
England 3
Germany 2
UK 2
USA 2
Indonesia 1
Name: b, dtype: int64
IIUC 您可以应用列表并使用 .str 检查长度,即
temp = df.groupby('groupid')['b'].apply(list).to_frame()
temp
b
groupid
1 [1, 2, 3]
3 [1]
4 [612, 612, 1]
mask = (temp['b'].str.len() == 1) & (temp['b'].str[0] == 1)
temp[mask].index.tolist()
#[3]
temp[~mask].index.tolist()
#[1, 4]
我会选择
#group by the group id and than apply count for how many b entries are equal to 1
groups = df.groupby("groupid").apply(lambda group:len([x for x in
group["b"].values.tolist() if x == 1]))
#keep the groups containing 1 b equal to 1
groups = groups[groups == 1]
#print the indecies of the result (the groupid values)
print groups.index.values
假设我有以下数据框:
#!/usr/bin/env python
import pandas as pd
df = pd.DataFrame([(1, 2, 1),
(1, 2, 2),
(1, 2, 3),
(4, 1, 612),
(4, 1, 612),
(4, 1, 1),
(3, 2, 1),
],
columns=['groupid', 'a', 'b'],
index=['India', 'France', 'England', 'Germany', 'UK', 'USA',
'Indonesia'])
print(df)
给出:
groupid a b
India 1 2 1
France 1 2 2
England 1 2 3
Germany 4 1 612
UK 4 1 612
USA 4 1 1
Indonesia 3 2 1
第 1 步
这一步可能没有必要/与我想象的不同。我实际上只对第 2 步感兴趣,但是有了这个可以帮助我思考它并解释我想要什么。
我想按 groupid (df.groupby(df['groupid'])
) 对数据进行分组,得到这样的结果:
groupid a b
1 [2] [1, 2, 3]
4 [1] [612, 1]
3 [2] [1]
第 2 步
然后我想找到在 b 列中只有一个条目且条目等于 1
的所有组 ID。
同样,我想找到所有具有多个条目或一个条目不是 1
的组 ID。
您可以比较 set
s,然后获取 list
s 的索引值:
mask = df.groupby('groupid')['b'].apply(set) == set([1])
print (mask)
groupid
1 False
3 True
4 False
Name: b, dtype: bool
i = mask.index[mask].tolist()
print (i)
[3]
j = mask.index[~mask].tolist()
print (j)
[1, 4]
对于新列使用 map
:
df['new'] = df['groupid'].map(df.groupby('groupid')['b'].apply(set) == set([1]))
print (df)
groupid a b new
India 1 2 1 False
France 1 2 2 False
England 1 2 3 False
Germany 4 1 612 False
UK 4 1 612 False
USA 4 1 1 False
Indonesia 3 2 1 True
旧解决方案:
您可以将 transform
with nunique
用于与原始 df 大小相同的新 Series
,因此可以将其与 1
进行比较以获得唯一性,然后链接另一个条件以与 [= 进行比较21=]:
mask = (df.groupby('groupid')['b'].transform('nunique') == 1) & (df['b'] == 1)
print (mask)
India False
France False
England False
Germany False
UK False
USA False
Indonesia True
Name: b, dtype: bool
对于 list
中的唯一值:
i = df.loc[mask, 'groupid'].unique().tolist()
print (i)
[3]
j = df.loc[~mask, 'groupid'].unique().tolist()
print (j)
[1, 4]
详情:
print (df.groupby('groupid')['b'].transform('nunique'))
India 3
France 3
England 3
Germany 2
UK 2
USA 2
Indonesia 1
Name: b, dtype: int64
IIUC 您可以应用列表并使用 .str 检查长度,即
temp = df.groupby('groupid')['b'].apply(list).to_frame()
temp
b
groupid
1 [1, 2, 3]
3 [1]
4 [612, 612, 1]
mask = (temp['b'].str.len() == 1) & (temp['b'].str[0] == 1)
temp[mask].index.tolist()
#[3]
temp[~mask].index.tolist()
#[1, 4]
我会选择
#group by the group id and than apply count for how many b entries are equal to 1
groups = df.groupby("groupid").apply(lambda group:len([x for x in
group["b"].values.tolist() if x == 1]))
#keep the groups containing 1 b equal to 1
groups = groups[groups == 1]
#print the indecies of the result (the groupid values)
print groups.index.values