Pandas 组依据的奇怪行为 - 对字符串列进行转换

Strange Behavior With Pandas Group By - Transform On String Columns

我遇到了 Pandas .groupby().transform() 的奇怪行为。这是生成数据集的代码:

df = pd.DataFrame({"Name" : ["Alice", "Bob", "Mallory", "Mallory", "Bob" , "Mallory"] ,
                   "Random_Number": [1223344, 373293832, 32738382392, 7273283232, 8239329, 23938832],
                   "City" : ["Seattle", "Seattle", "Portland", "Seattle", "Seattle", "Portland"]})

这是我为 transform() 编写的函数。

# this function will attach each value in string col with the number of elements in the each city group
# if the col type is not an object, then return 0 for all rows. 

def some(x): 
    if x.dtype == 'object':
        return x + '--' + str(len(x))
    else:
        return 0

然后我将我的函数与转换一起使用 - 完美地工作并得到我想要的。

df_2 = stack.groupby(["City"])['Name','Random_Number'].transform(some)

然而,当我将 col 的顺序从 ['Name','Random_Number'] 切换到 ['Random_Number','Name']

时,奇怪的事情发生了
df_2 = stack.groupby(["City"])['Random_Number','Name'].transform(some)

当您查看 'Name' 列中的单元格时,似乎 pandas 将所有内容多次放入一个单元格中:

df_2.iloc[0,1]
# Return: 
# 0      Alice--4
# 1        Bob--4
# 3    Mallory--4
# 4        Bob--4
# Name: Name, dtype: object

为什么会这样?

问题出在您的return

如果 x.dtype == 'object' 那么你 return 一个系列所以你的 transform 聚合 不会减少 (return 是与原始长度相同)。如果采用另一条路径,return 是单个标量 0,pandas 将其视为缩减(return 是每组单个值)。

因为您的聚合在缩减方面有所不同,无论内部 pandas 用来找出要采用的路径以及如何将其带回原始 DataFrame,都会根据您的列顺序感到困惑。当 'Random_Number' 是第一个时,它检查函数,发现函数减少并采用一条路径,但如果 'Name' 首先出现,它检查,发现函数没有减少并采用另一条路径进行计算。

您可以通过确保两个 returns 不减少

来解决这个问题
def some(x): 
    if x.dtype == 'object':
        return x + '--' + str(len(x))
    else:
        return [0]*len(x)

df.groupby('City')[['Random_Number','Name']].transform(some)
#   Random_Number        Name
#0              0    Alice--4
#1              0      Bob--4
#2              0  Mallory--2
#3              0  Mallory--4
#4              0      Bob--4
#5              0  Mallory--2

df.groupby('City')[['Name', 'Random_Number']].transform(some)
#         Name  Random_Number
#0    Alice--4              0
#1      Bob--4              0
#2  Mallory--2              0
#3  Mallory--4              0
#4      Bob--4              0
#5  Mallory--2              0