jpp*_*jpp 11 python dataframe pandas pandas-groupby
我不明白groupby+ transform操作可接受哪些功能.通常情况下,我最终只是猜测,测试,还原直到某些工作正常,但我觉得应该有一种系统的方法来确定解决方案是否有效.
这是一个最小的例子.首先,让我们用groupby+ apply有set:
df = pd.DataFrame({'a': [1,2,3,1,2,3,3], 'b':[1,2,3,1,2,3,3], 'type':[1,0,1,0,1,0,1]})
g = df.groupby(['a', 'b'])['type'].apply(set)
print(g)
a b
1 1 {0, 1}
2 2 {0, 1}
3 3 {0, 1}
Run Code Online (Sandbox Code Playgroud)
这工作正常,但我希望set在原始数据帧的新列中进行组计算.所以我尝试使用transform:
df['g'] = df.groupby(['a', 'b'])['type'].transform(set)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
---> 23 df['g'] = df.groupby(['a', 'b'])['type'].transform(set)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'set'
Run Code Online (Sandbox Code Playgroud)
这是我在Pandas v0.19.0中看到的错误.在v0.23.0中,我看到了TypeError: 'set' type is unordered.当然,我可以映射一个特定的索引来实现我的结果:
g = df.groupby(['a', 'b'])['type'].apply(set)
df['g'] = df.set_index(['a', 'b']).index.map(g.get)
print(df)
a b type g
0 1 1 1 {0, 1}
1 2 2 0 {0, 1}
2 3 3 1 {0, 1}
3 1 1 0 {0, 1}
4 2 2 1 {0, 1}
5 3 3 0 {0, 1}
6 3 3 1 {0, 1}
Run Code Online (Sandbox Code Playgroud)
但我认为好处transform是避免这种明确的映射.我哪里做错了?
raf*_*elc 13
我相信,首先,使用这些功能有一定的直觉空间,因为它们非常有意义.
在您的第一个结果中,您实际上并没有尝试转换您的值,而是聚合它们(这将按照您的预期方式工作).
但是进入代码,transform文档在说这些内容时非常具有启发性
返回与组块大小相同或可广播到组块大小的结果.
当你这样做
df.groupby(['a', 'b'])['type'].transform(some_func)
Run Code Online (Sandbox Code Playgroud)
实际上,您正在使用函数将每个组中的每个pd.Series对象转换为新对象some_func.但事实是,这个新对象应该具有与组相同的大小,或者可以广播到块的大小.
因此,如果使用tuple或转换系列list,则基本上将转换对象
0 1
1 2
2 3
dtype: int64
Run Code Online (Sandbox Code Playgroud)
成
[1,2,3]
Run Code Online (Sandbox Code Playgroud)
但请注意,这些值现在已分配回各自的索引,这就是您在transform操作中看不到差异的原因.具有.iloc[0]来自pd.Serieswill 的值的行现在具有[1,2,3][0]变换列表中的值(同样适用于元组)等.请注意,这里的排序和大小很重要,因为否则你可能搞乱你的组并且转换不起作用(这正是为什么set在这种情况下不能使用的正确功能).
引用文本的第二部分说"可播放到组块的大小".
这意味着您还可以将您转换pd.Series为可在所有行中使用的对象.例如
df.groupby(['a', 'b'])['type'].transform(lambda k: 50)
Run Code Online (Sandbox Code Playgroud)
会工作.为什么?即使50不可迭代,也可以通过在初始位置的所有位置重复使用该值进行广播pd.Series.
你为什么apply要用套装?
因为该apply方法在结果中没有这种大小约束.它实际上有三种不同的结果类型,它可以推断您是要扩展,缩小还是广播结果.请注意,您无法减少转换*
默认情况下(
result_type=None),最终返回类型是从应用函数的返回类型推断出来的.result_type:{'expand','reduce','broadcast',None},默认无这些只在axis=1(列)时起作用:
'expand':类似列表的结果将变为列.
'reduce':尽可能返回系列,而不是扩展类似列表的结果.这与'expand'相反.
'broadcast':结果将广播到DataFrame的原始形状,原始索引和列将被保留.
| 归档时间: |
|
| 查看次数: |
5256 次 |
| 最近记录: |