我有一个多索引数据框我在这里重新创建了一小部分。
每个“实例”都有不同数量的ID。每个ID都有两个因子,Factor1和Factor2。我想要两个新专栏。第一个很简单,100除以实例中的ID数(Count)。这是'evenSpread'专栏。
Factor1 Factor2 evenSpread dropONE
Place Instance Count ID
Home 1 7 1 20 18 14.285714 16.666667
2 22 19 14.285714 16.666667
4 36 40 14.285714 16.666667
5 32 30 14.285714 16.666667
6 1 7 14.285714 16.666667
7 99 90 14.285714 16.666667
8 5 9 14.285714 16.666667
2 8 1 10 8 12.500000 14.285714
3 20 19 12.500000 14.285714
4 30 35 12.500000 14.285714
5 40 55 12.500000 14.285714
6 70 50 12.500000 14.285714
7 50 60 12.500000 14.285714
8 60 52 12.500000 14.285714
9 70 88 12.500000 14.285714
第二个('dropONE')更加困难,我确信有一些概念我不知道如何正确完成。我想在Factor1中删除其中一个具有最高值的ID,如果包含100 /(count-1)则填充该列,如果不包含则填充0。第二部分是因为如果因子1的最大值发生了两次,那么检查因子2并丢弃它们中的较小者。
我不知道这是否可以在一个作业中完成,而不必创建任何其他列,但我很难过。
对于实例1中的所有,dropONE列应为16.66667,除了ID为7的0,其中因子1为99.对于实例2中的所有应该为14.285714,除了ID为6的0,其中因子1为70(F1的最大值) )和因子2是50(50低于88)。这就是我想要看到的:
Factor1 Factor2 evenSpread dropONE
Place Instance Count ID
Home 1 7 1 20 18 14.285714 16.666667
2 22 19 14.285714 16.666667
4 36 40 14.285714 16.666667
5 32 30 14.285714 16.666667
6 1 7 14.285714 16.666667
7 99 90 14.285714 0
8 5 9 14.285714 16.666667
2 8 1 10 8 12.500000 14.285714
3 20 19 12.500000 14.285714
4 30 35 12.500000 14.285714
5 40 55 12.500000 14.285714
6 70 50 12.500000 0
7 50 60 12.500000 14.285714
8 60 52 12.500000 14.285714
9 70 88 12.500000 14.285714
我甚至无法获得第一个工作条件,更不用说第二个了。到目前为止,这是我的代码。
import numpy as np
import pandas as pd
my_data = {'Place': ['Home', 'Home', 'Home', 'Home', 'Home', 'Home', 'Home',
'Home', 'Home', 'Home', 'Home', 'Home', 'Home', 'Home', 'Home'],
'Instance': [1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2],
'Count': [7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8],
'ID': [1, 2, 4, 5, 6, 7, 8,
1, 3, 4, 5, 6, 7, 8, 9],
'Factor1': [20, 22, 36, 32, 1, 99, 5,
10, 20, 30, 40, 70, 50, 60, 70],
'Factor2': [18, 19, 40, 30, 7, 90, 9,
8, 19, 35, 55, 50, 60, 52, 88],
}
df = pd.DataFrame(my_data)
df = df[['Place', 'Instance', 'Count', 'ID', 'Factor1', 'Factor2']]
df.set_index(['Place', 'Instance', 'Count', 'ID'], inplace=True)
print(df)
df['evenSpread'] = 100 / df.index.get_level_values('Count')
df['dropONE'] = 100 / (df.index.get_level_values('Count') - 1) # WRONG AS WRITTEN
print(df)
# df['dropONE'] = np.where(df['Factor1'] == df.groupby(level=[0, 1, 2])['Factor1'].max(), 0, 1)
print(df)
print(df.groupby(level=[0, 1, 2])['Factor1'].max())
np.where中的groupby无法正常工作并出错,我知道这是因为我正在比较不同大小的对象,但不确定如何正确执行此操作。
顺便说一下,群组中的最后一次打印显示了这一点:
Place Instance Count
Home 1 7 99
2 8 70
Name: Factor1, dtype: int64
非常感谢。
编辑#1
不确定这是否有帮助,但我使用以下内容对每个组进行了分类。那么也许有一种方法可以根据每个组的顺序创建一个True / False标志列?同样,一个组将是实例中的所有内容。
print(df.sort_values(by=['Factor1', 'Factor2'], ascending=[True, False]).sort_index(
level='Instance', sort_remaining=False))
这给出了:
Factor1 Factor2 evenSpread dropONE
Place Instance Count ID
Home 1 7 6 1 7 14.285714 16.666667
8 5 9 14.285714 16.666667
1 20 18 14.285714 16.666667
2 22 19 14.285714 16.666667
5 32 30 14.285714 16.666667
4 36 40 14.285714 16.666667
7 99 90 14.285714 16.666667
2 8 1 10 8 12.500000 14.285714
3 20 19 12.500000 14.285714
4 30 35 12.500000 14.285714
5 40 55 12.500000 14.285714
7 50 60 12.500000 14.285714
8 60 52 12.500000 14.285714
6 70 88 12.500000 14.285714
9 70 50 12.500000 14.285714
答案 0 :(得分:1)
数小时的搜索和反复试验,我学到了一些东西。排序是关键。以下内容改编自This question
def replace_first_x(group):
group.iloc[-1, -1:] = 0
return group
df = df.groupby(level=[0, 1, 2]).apply(replace_first_x)
print(df)
我的输出!
Factor1 Factor2 evenSpread dropONE
Place Instance Count ID
Home 1 7 6 1 7 14.285714 16.666667
8 5 9 14.285714 16.666667
1 20 18 14.285714 16.666667
2 22 19 14.285714 16.666667
5 32 30 14.285714 16.666667
4 36 40 14.285714 16.666667
7 99 90 14.285714 0.000000
2 8 1 10 8 12.500000 14.285714
3 20 19 12.500000 14.285714
4 30 35 12.500000 14.285714
5 40 55 12.500000 14.285714
7 50 60 12.500000 14.285714
8 60 52 12.500000 14.285714
9 70 88 12.500000 14.285714
6 70 50 12.500000 0.000000
我很好奇是否有任何内置功能或更好的方法来做到这一点。这有效,但有点慢(df超过500k行)。