按组划分的唯一值百分比
% of Unique Values by Group
我想创建下面的列 Stories_%
来对唯一值 % 进行分类。
SubID Stories Stories_%
0 102F2 2 1 (20%), 2 (80%)
1 102F2 2 1 (20%), 2 (80%)
2 102F2 2 1 (20%), 2 (80%)
3 102F2 2 1 (20%), 2 (80%)
4 102F2 1 1 (20%), 2 (80%)
5 132F2 2 1 (60%), 2 (40%)
6 132F2 1 1 (60%), 2 (40%)
7 132F2 1 1 (60%), 2 (40%)
8 132F2 2 1 (60%), 2 (40%)
9 132F2 1 1 (60%), 2 (40%)
我会删除重复项并删除 Stories
所以最终的 table 看起来像这样:
SubID Stories_%
0 102F2 1 (20%), 2 (80%)
1 132F2 1 (60%), 2 (40%)
我首先创建了一个包含所有唯一值的列表(如下):
unique_stories = df.groupby(["SubID"])['Stories'].unique().astype(int)
unique_stories
SubID
001C5 ['2']
001C6 ['2']
002I2 ['2']
004C6 ['2']
005L2 ['2']
...
709E1 ['1' '2']
725E1 ['2' '1']
730E1 ['2' '1']
我遇到的问题是获取每个唯一计数的 %s。
我试过了...
df.groupby(['SubID'])['Stories'].count()
...但这只会创建总计数,而不是该类别中每个唯一值的计数。
我研究了很多帖子,但只能显示整个列的总计数、唯一值计数和唯一值计数,而不是按组等。
有没有办法做到这一点?
方法一:可以使用groupby
+value_counts
:
s = df.groupby('SubID')['Stories']\
.value_counts(normalize=True, sort=False).map('{:.0%}'.format)
(s.index.get_level_values(1).astype(str) + ' (' + s + ')')\
.groupby(level=0).agg(','.join).reset_index(name='Stories %')
方法 2: 或者你可以使用 Counter
来自 collections
:
def normalize():
d = {}
for i, g in df.groupby('SubID'):
c = Counter(g['Stories'])
d[i] = ', '.join(f'{k} ({v / sum(c.values()):.0%})'
for k, v in c.items())
return d
pd.Series(normalize(), name='Stories %').rename('SubID').reset_index()
SubID Stories %
0 102F2 1 (20%),2 (80%)
1 132F2 1 (60%),2 (40%)
如果您接受存储相同信息的稍微不同的格式,但利用了 MultiIndex(这将使未来的操作和计算更简单),那么我们可以使用 gropuby
+ size
然后 sum
.
s = df.groupby(['SubID', 'Stories']).size()
s = s/s.sum(level=0) # Divide by the total number within each `'SubID'`
SubID Stories
102F2 1 0.2
2 0.8
132F2 1 0.6
2 0.4
dtype: float64
我想创建下面的列 Stories_%
来对唯一值 % 进行分类。
SubID Stories Stories_%
0 102F2 2 1 (20%), 2 (80%)
1 102F2 2 1 (20%), 2 (80%)
2 102F2 2 1 (20%), 2 (80%)
3 102F2 2 1 (20%), 2 (80%)
4 102F2 1 1 (20%), 2 (80%)
5 132F2 2 1 (60%), 2 (40%)
6 132F2 1 1 (60%), 2 (40%)
7 132F2 1 1 (60%), 2 (40%)
8 132F2 2 1 (60%), 2 (40%)
9 132F2 1 1 (60%), 2 (40%)
我会删除重复项并删除 Stories
所以最终的 table 看起来像这样:
SubID Stories_%
0 102F2 1 (20%), 2 (80%)
1 132F2 1 (60%), 2 (40%)
我首先创建了一个包含所有唯一值的列表(如下):
unique_stories = df.groupby(["SubID"])['Stories'].unique().astype(int)
unique_stories
SubID
001C5 ['2']
001C6 ['2']
002I2 ['2']
004C6 ['2']
005L2 ['2']
...
709E1 ['1' '2']
725E1 ['2' '1']
730E1 ['2' '1']
我遇到的问题是获取每个唯一计数的 %s。
我试过了...
df.groupby(['SubID'])['Stories'].count()
...但这只会创建总计数,而不是该类别中每个唯一值的计数。
我研究了很多帖子,但只能显示整个列的总计数、唯一值计数和唯一值计数,而不是按组等。
有没有办法做到这一点?
方法一:可以使用groupby
+value_counts
:
s = df.groupby('SubID')['Stories']\
.value_counts(normalize=True, sort=False).map('{:.0%}'.format)
(s.index.get_level_values(1).astype(str) + ' (' + s + ')')\
.groupby(level=0).agg(','.join).reset_index(name='Stories %')
方法 2: 或者你可以使用 Counter
来自 collections
:
def normalize():
d = {}
for i, g in df.groupby('SubID'):
c = Counter(g['Stories'])
d[i] = ', '.join(f'{k} ({v / sum(c.values()):.0%})'
for k, v in c.items())
return d
pd.Series(normalize(), name='Stories %').rename('SubID').reset_index()
SubID Stories %
0 102F2 1 (20%),2 (80%)
1 132F2 1 (60%),2 (40%)
如果您接受存储相同信息的稍微不同的格式,但利用了 MultiIndex(这将使未来的操作和计算更简单),那么我们可以使用 gropuby
+ size
然后 sum
.
s = df.groupby(['SubID', 'Stories']).size()
s = s/s.sum(level=0) # Divide by the total number within each `'SubID'`
SubID Stories
102F2 1 0.2
2 0.8
132F2 1 0.6
2 0.4
dtype: float64