将组 ID 返回到 pandas 数据帧
Posted
技术标签:
【中文标题】将组 ID 返回到 pandas 数据帧【英文标题】:Get group id back into pandas dataframe 【发布时间】:2013-02-10 22:20:00 【问题描述】:对于数据框
In [2]: df = pd.DataFrame('Name': ['foo', 'bar'] * 3,
...: 'Rank': np.random.randint(0,3,6),
...: 'Val': np.random.rand(6))
...: df
Out[2]:
Name Rank Val
0 foo 0 0.299397
1 bar 0 0.909228
2 foo 0 0.517700
3 bar 0 0.929863
4 foo 1 0.209324
5 bar 2 0.381515
我有兴趣按名称和排名进行分组,并可能获取汇总值
In [3]: group = df.groupby(['Name', 'Rank'])
In [4]: agg = group.agg(sum)
In [5]: agg
Out[5]:
Val
Name Rank
bar 0 1.839091
2 0.381515
foo 0 0.817097
1 0.209324
但我想在原始 df
中获取一个字段,其中包含该行的组号,例如
In [13]: df['Group_id'] = [2, 0, 2, 0, 3, 1]
In [14]: df
Out[14]:
Name Rank Val Group_id
0 foo 0 0.299397 2
1 bar 0 0.909228 0
2 foo 0 0.517700 2
3 bar 0 0.929863 0
4 foo 1 0.209324 3
5 bar 2 0.381515 1
在 pandas 中有没有好的方法来做到这一点?
我可以用python得到它,
In [16]: from itertools import count
In [17]: c = count()
In [22]: group.transform(lambda x: c.next())
Out[22]:
Val
0 2
1 0
2 2
3 0
4 3
5 1
但它在大型数据帧上相当慢,所以我认为可能有更好的内置 pandas 方式来做到这一点。
【问题讨论】:
【参考方案1】:使用来自 pandas 0.20.2+ 的 GroupBy.ngroup
:
df["GroupId"] = df.groupby(["Name", "Rank"]).ngroup()
print (df)
Name Rank Val GroupId
0 foo 2 0.451724 4
1 bar 0 0.944676 0
2 foo 0 0.822390 2
3 bar 2 0.063603 1
4 foo 1 0.938892 3
5 bar 2 0.332454 1
【讨论】:
【参考方案2】:正确的解决方法是使用grouper.label_info
:
df["GroupId"] = df.groupby(["Name", "Rank"]).grouper.label_info
它会自动将df
数据框中的每一行与相应的组标签相关联。
【讨论】:
这之前有效,但 label_info 似乎已在 pandas 1.0 中删除【参考方案3】:DataFrameGroupBy.grouper
对象中存储了很多方便的东西。例如:
>>> df = pd.DataFrame('Name': ['foo', 'bar'] * 3,
'Rank': np.random.randint(0,3,6),
'Val': np.random.rand(6))
>>> grouped = df.groupby(["Name", "Rank"])
>>> grouped.grouper.
grouped.grouper.agg_series grouped.grouper.indices
grouped.grouper.aggregate grouped.grouper.labels
grouped.grouper.apply grouped.grouper.levels
grouped.grouper.axis grouped.grouper.names
grouped.grouper.compressed grouped.grouper.ngroups
grouped.grouper.get_group_levels grouped.grouper.nkeys
grouped.grouper.get_iterator grouped.grouper.result_index
grouped.grouper.group_info grouped.grouper.shape
grouped.grouper.group_keys grouped.grouper.size
grouped.grouper.groupings grouped.grouper.sort
grouped.grouper.groups
等等:
>>> df["GroupId"] = df.groupby(["Name", "Rank"]).grouper.group_info[0]
>>> df
Name Rank Val GroupId
0 foo 0 0.302482 2
1 bar 0 0.375193 0
2 foo 2 0.965763 4
3 bar 2 0.166417 1
4 foo 1 0.495124 3
5 bar 2 0.728776 1
grouper.group_info[0]
可能有一个更好的别名潜伏在某个地方,但无论如何这应该可以工作。
【讨论】:
另一个别名好像是grouped.grouper.labels[0]
唯一的问题是石斑鱼没有记录,不保证它不会破裂。
三年后,这件事仍然没有记录。但是很容易发现df.grouper
有BaseGrouper
类。 group_info
方法在代码中定义为 here,您可以进一步追溯以确认以下内容:1) group_info[1]
是唯一组标识符的数组,2) 行 @ 的组标识符987654332@是group_info[0][i]
,3)group_info[3]
是组数
也许这是我对 python 的天真,但我很惊讶没有一个简单的、记录在案的方法。我提出这个问题是因为我想使用sklearn.cross_validation.StratifiedShuffleSplit 并在几个不同列的独特组合中进行分层。这个组 ID 正是我完成这项工作所需的单列,但很难找到。我很想知道这是否是对熊猫的滥用。
@jflournoy:巧合的是,我现在有一个 PR,可以通过规范的方式访问这些信息。以上是关于将组 ID 返回到 pandas 数据帧的主要内容,如果未能解决你的问题,请参考以下文章
如何从 for 循环返回多个具有唯一名称的 pandas 数据帧?
如何将 Spark 数据帧转换为 Pandas 并返回 Kedro?