每月基于列的大值的子集数据框
Subset dataframe based on large values of a column per month
我有一个这样的 df:
month
stock
MV
1994-07
A
50
1994-07
B
60
1994-07
C
70
1994-07
D
80
1994-08
A
90
1994-08
B
60
1994-08
C
70
1994-08
D
95
1994-08
E
100
1994-08
F
110
我想以一种我每月只有最高 MV 的 50% 的方式对我的 df 进行子集化。对于 July/1994 我只有 4 个股票,所以 50% 将是 2 个最高的 MV。之后的一个月,我有 6 只股票,这给了我 3 个最高值:
month
stock
MV
1994-07
C
70
1994-07
D
80
1994-08
D
95
1994-08
E
100
1994-08
F
110
我试过:
df = df.groupby(pd.Grouper(freq="M")).nlargest(2, "MV")
但我收到错误:AttributeError: 'DataFrameGroupBy' object has no attribute 'nlargest'
此外,每个月的 n 值都需要不同。我也不知道怎么处理。
你需要通过apply
df = df.groupby(pd.Grouper(freq="M")).apply(lambda x : x.nlargest(2, "MV"))
df.groupby('month').apply(lambda monthly_data: monthly_data[monthly_data['MV'] >= monthly_data['MV'].median())
您需要使用 apply
并计算最终长度:
df.groupby(pd.Grouper(freq="M")).apply(lambda g: g.nlargest(len(g)//2, 'MV'))
将提供的数据作为字符串:
(df.groupby('month', as_index=False, group_keys=False) # use pd.Grouper if needed here
.apply(lambda g: g.nlargest(len(g)//2, 'MV'))
.sort_values(by=['month', 'MV'])
)
输出:
month stock MV
2 1994-07 C 70
3 1994-07 D 80
7 1994-08 D 95
8 1994-08 E 100
9 1994-08 F 110
您可以对值进行排序,然后 select lambda 函数中值长度的 50%:
df = (df.sort_values(['month','MV'])
.groupby(pd.Grouper(freq="M"), group_keys=False)
.apply(lambda x: x.head(int(len(x)) // 2)))
您可以使用median
(或quantile
):
out = df.loc[df['MV'] > df.groupby('month')['MV'].transform('median')]
print(out)
# Output
month stock MV
2 1994-07 C 70
3 1994-07 D 80
7 1994-08 D 95
8 1994-08 E 100
9 1994-08 F 110
与 quantile
相同的版本,但如果您想更改百分比,您有更多的控制权:
out = df.loc[df['MV'] > df.groupby('month')['MV'].transform('quantile', 0.5)]
print(out)
# Output
month stock MV
2 1994-07 C 70
3 1994-07 D 80
7 1994-08 D 95
8 1994-08 E 100
9 1994-08 F 110
我有一个这样的 df:
month | stock | MV |
---|---|---|
1994-07 | A | 50 |
1994-07 | B | 60 |
1994-07 | C | 70 |
1994-07 | D | 80 |
1994-08 | A | 90 |
1994-08 | B | 60 |
1994-08 | C | 70 |
1994-08 | D | 95 |
1994-08 | E | 100 |
1994-08 | F | 110 |
我想以一种我每月只有最高 MV 的 50% 的方式对我的 df 进行子集化。对于 July/1994 我只有 4 个股票,所以 50% 将是 2 个最高的 MV。之后的一个月,我有 6 只股票,这给了我 3 个最高值:
month | stock | MV |
---|---|---|
1994-07 | C | 70 |
1994-07 | D | 80 |
1994-08 | D | 95 |
1994-08 | E | 100 |
1994-08 | F | 110 |
我试过:
df = df.groupby(pd.Grouper(freq="M")).nlargest(2, "MV")
但我收到错误:AttributeError: 'DataFrameGroupBy' object has no attribute 'nlargest' 此外,每个月的 n 值都需要不同。我也不知道怎么处理。
你需要通过apply
df = df.groupby(pd.Grouper(freq="M")).apply(lambda x : x.nlargest(2, "MV"))
df.groupby('month').apply(lambda monthly_data: monthly_data[monthly_data['MV'] >= monthly_data['MV'].median())
您需要使用 apply
并计算最终长度:
df.groupby(pd.Grouper(freq="M")).apply(lambda g: g.nlargest(len(g)//2, 'MV'))
将提供的数据作为字符串:
(df.groupby('month', as_index=False, group_keys=False) # use pd.Grouper if needed here
.apply(lambda g: g.nlargest(len(g)//2, 'MV'))
.sort_values(by=['month', 'MV'])
)
输出:
month stock MV
2 1994-07 C 70
3 1994-07 D 80
7 1994-08 D 95
8 1994-08 E 100
9 1994-08 F 110
您可以对值进行排序,然后 select lambda 函数中值长度的 50%:
df = (df.sort_values(['month','MV'])
.groupby(pd.Grouper(freq="M"), group_keys=False)
.apply(lambda x: x.head(int(len(x)) // 2)))
您可以使用median
(或quantile
):
out = df.loc[df['MV'] > df.groupby('month')['MV'].transform('median')]
print(out)
# Output
month stock MV
2 1994-07 C 70
3 1994-07 D 80
7 1994-08 D 95
8 1994-08 E 100
9 1994-08 F 110
与 quantile
相同的版本,但如果您想更改百分比,您有更多的控制权:
out = df.loc[df['MV'] > df.groupby('month')['MV'].transform('quantile', 0.5)]
print(out)
# Output
month stock MV
2 1994-07 C 70
3 1994-07 D 80
7 1994-08 D 95
8 1994-08 E 100
9 1994-08 F 110