我的数据库结构是这样的,我有单位,属于几个组,并有不同的变量(我专注于一个,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
等。现在我想做的是测量一些“强度”变量,即每组和每年的单位数量,我想把它重新放回数据库。
到目前为止,我正在做
asd = df.drop_duplicates(cols=['unitid', 'year'])
groups = asd.groupby(['year', 'groupid'])
intensity = groups.size()
然后强度看起来像
year groupid
1961 2000 4
2030 3
2040 1
2221 1
2300 2
但是,我不知道如何将它们放回旧的数据帧中。我可以通过intensity[0]
访问它们,但intensity.loc()
给出一个LocIndexer不可调用的错误。
其次,如果我可以扩展强度,那将是非常好的。而不是“每组每年的单位”,它将是“每组每年的单位,按当年每组的平均/最大单位换算”。如果{t,g}表示组年单元格,则为:
也就是说,如果我的简单强度变量(时间和组)被称为强度(t,g),我想创建relativeIntensity(t,g) = intensity(t,g)/mean(intensity(t=t,g=:))
- 如果这个假代码有助于使我自己清楚。
谢谢!
更新
为了便于阅读,请在此处(明确地)提供答案。第一部分由
解决intensity = intensity.reset_index()
df['intensity'] = intensity[0]
答案 0 :(得分:1)
这是a multi-index。您可以通过调用.reset_index()
到结果数据帧来重置索引。或者,您可以在计算分组操作时将其禁用,方法是将as_index=False
指定为groupby()
,例如:
intensity = asd.groupby(["year", "groupid"], as_index=False).size()
关于你的第二个问题,我不确定你在Instead of "units per group-year", it would be "units per group-year, scaled by average/max units per group-year in that year".
中的意思。如果您想通过intensity / mean(intensity)
计算“强度”,可以使用transform
方法,例如:
asd.groupby(["year", "groupid"])["X"].transform(lambda x: x/mean(x))
这是你要找的吗?
如果您想计算intensity / mean(intensity)
,其中mean(intensity)
仅基于year
而非year/groupid
子集,那么您首先必须创建mean(intensity)
}仅基于year
,例如:
intensity["mean_intensity_only_by_year"] = intensity.groupby(["year"])["X"].transform(mean)
然后为所有intensity / mean(intensity)
子集计算year/groupid
,其中mean(intensity)
仅来自year
子集:
intensity["relativeIntensity"] = intensity.groupby(["year", "groupid"]).apply(lambda x: pd.DataFrame(
{"relativeIntensity": x["X"] / x["mean_intensity_only_by_year"] }
))
也许这就是你要找的,对吗?
答案 1 :(得分:1)
实际上,几天之后,我发现这个双重问题的第一个答案是错误的。也许有人可以详细说明.size()
实际上做了什么,但这是为了万一有人用谷歌搜索这个问题并没有走错路。
事实证明,.size()
的行数比原始对象少(如果我使用reset_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']