Python Pandas groupby:计算(相对)大小并保存在原始数据帧中

Python Pandas groupby:计算(相对)大小并保存在原始数据帧中,python,pandas,Python,Pandas,我的数据库结构是这样的:我有属于多个组的单元,并且有不同的变量(对于这个问题,我关注的是一个X)。然后我们有基于年份的记录。所以数据库看起来像 unitid, groupid, year, X 0 1 1, 1990, 5 1 2 1, 1990, 2 2 2 1, 1991, 3 3 3 2, 1990, 10 year groupid 1961 2000 4

我的数据库结构是这样的:我有属于多个组的单元,并且有不同的变量(对于这个问题,我关注的是一个X)。然后我们有基于年份的记录。所以数据库看起来像

    unitid, groupid, year, X
0        1        1, 1990, 5
1        2        1, 1990, 2
2        2        1, 1991, 3
3        3        2, 1990, 10
year groupid
1961    2000    4
        2030    3
        2040    1
        2221    1
        2300    2
等等,现在我想做的是测量一些“强度”变量,即每组和每年的单位数量,我想把它放回数据库

到目前为止,我正在做

asd = df.drop_duplicates(cols=['unitid', 'year'])
groups = asd.groupby(['year', 'groupid'])
intensity = groups.size()
然后强度看起来像

    unitid, groupid, year, X
0        1        1, 1990, 5
1        2        1, 1990, 2
2        2        1, 1991, 3
3        3        2, 1990, 10
year groupid
1961    2000    4
        2030    3
        2040    1
        2221    1
        2300    2
但是,我不知道如何将它们放回旧的数据帧中。我可以通过
intensity[0]
访问它们,但是
intensity.loc()
给出了LocIndexer不可调用的错误

第二,如果我能测量强度,那将是非常好的。而不是“集团年单位数”,而是“集团年单位数,按该年集团年平均/最大单位数缩放”。如果{t,g}表示组年单元,则为:

也就是说,如果我的简单强度变量(用于时间和组)称为强度(t,g),我想创建
相对强度(t,g)=强度(t,g)/mean(强度(t=t,g=:)
——如果这个伪代码有助于我弄清楚

谢谢

更新

为了便于阅读,请(明确地)将答案放在这里。第一部分由

intensity = intensity.reset_index()
df['intensity'] = intensity[0]
是的。您可以通过对结果数据帧调用
.reset\u index()
来重置索引。或者,您可以在计算分组操作时禁用它,方法是将
指定为
groupby()
,例如:

intensity = asd.groupby(["year", "groupid"], as_index=False).size()
至于你的第二个问题,我不知道你在
中的意思是什么,而不是“每个组年的单位”,而是“每个组年的单位,按当年每个组年的平均/最大单位进行缩放”。
。如果要通过
强度/平均值(强度)
计算“强度”,可以使用
变换
方法,如:

asd.groupby(["year", "groupid"])["X"].transform(lambda x: x/mean(x))
这就是你要找的吗

更新 如果要计算强度/平均(强度)
,其中
mean(强度)
仅基于
year
而非
year/groupid
子集,则首先必须仅基于
year
创建
平均(强度)
,如:

intensity["mean_intensity_only_by_year"] = intensity.groupby(["year"])["X"].transform(mean)
然后计算所有
year/groupid
子集的
强度/平均值(强度)
,其中
平均值(强度)
仅从
year
子集得出:

intensity["relativeIntensity"] = intensity.groupby(["year", "groupid"]).apply(lambda x: pd.DataFrame(
                        {"relativeIntensity": x["X"] / x["mean_intensity_only_by_year"] }
                    ))

也许这就是你想要的,对吧?

事实上,几天后,我发现这个双重问题的第一个答案是错误的。也许有人可以详细说明
.size()
实际上做了什么,但这只是为了防止有人用谷歌搜索这个问题时没有走错我的路

结果是
.size()
的行数比原始对象少得多(如果我使用
reset\u index()
,尽管我试图将大小堆叠回原始对象,但仍有许多行保留了
NaN

groups = asd.groupby(['year', 'groupid'])
intensity = groups.apply(lambda x: len(x))
asd.set_index(['year', 'groupid'], inplace=True)
asd['intensity'] = intensity
或者,我们也可以这样做

groups = asd.groupby(['fyearq' , 'sic'])
# change index to save groupby-results
asd= asd.set_index(['fyearq', 'sic'])
asd['competition'] = groups.size()
我的问题的第二部分是通过

# relativeSize
def computeMeanInt(group):
    group = group.reset_index()
    # every group has exactly one weight in the mean:
    sectors = group.drop_duplicates(cols=['group'])
    n = len(sectors)
    val = sum(sectors.competition)
    return float(val) / n


result = asd.groupby(level=0).apply(computeMeanInt)
asd= asd.reset_index().set_index('fyearq')
asd['meanIntensity'] = result
# if you don't reset index, everything crashes (too intensive, bug, whatever)
asd.reset_index(inplace=True)
asd['relativeIntensity'] = asd['intensity']/asd['meanIntensity']

在我消化第一部分之前,快速反馈到第二部分:几乎。我想要平均值(x),但不是整个数据集的平均值(x),而是同一年数据的平均值(x)。
mean(x)
是基于组而不是整个数据集计算的。因此在本例中,每个
mean(x)
是根据每个
year/groupid
子集计算的。或者你可能只想根据
year
来计算,而不是只根据
year/groupid
组合?year来计算。这应该是关于“强度”的,就像问题的第一部分一样。我刚刚注意到了这一点(更紧急)问题,我其实不需要介绍X-这有帮助吗?更新。至于“强度”,我只是知道它是关于物理的,但我对它知之甚少或一无所知。。。