Python 数据帧窗口函数

Python 数据帧窗口函数,python,pandas,Python,Pandas,我正试图像使用SQL窗口函数一样操作我的数据帧。考虑下面的样本集: import pandas as pd df = pd.DataFrame({'fruit' : ['apple', 'apple', 'apple', 'orange', 'orange', 'orange', 'grape', 'grape', 'grape'], 'test' : [1, 2, 1, 1, 2, 1, 1, 2, 1], 'analysis' :

我正试图像使用SQL窗口函数一样操作我的数据帧。考虑下面的样本集:

import pandas as pd

df = pd.DataFrame({'fruit' : ['apple', 'apple', 'apple', 'orange', 'orange', 'orange', 'grape', 'grape', 'grape'],
               'test' : [1, 2, 1, 1, 2, 1, 1, 2, 1],
               'analysis' : ['full', 'full', 'partial', 'full', 'full', 'partial', 'full', 'full', 'partial'],
               'first_pass' : [12.1, 7.1, 14.3, 19.1, 17.1, 23.4, 23.1, 17.2, 19.1],
               'second_pass' : [20.1, 12.0, 13.1, 20.1, 18.5, 22.7, 14.1, 17.1, 19.4],
               'units' : ['g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g'],
               'order' : [2, 1, 3, 2, 1, 3, 3, 2, 1]})
+--------+------+----------+------------+-------------+-------+-------+ |水果|测试|分析|一级|二级|订单|单位| +--------+------+----------+------------+-------------+-------+-------+ |苹果| 1 |满| 12.1 | 20.1 | 2 | g| |苹果| 2 |全| 7.1 | 12.0 | 1 | g| |苹果| 1 |部分| 14.3 | 13.1 | 3 | g| |橙色| 1 |满| 19.1 | 20.1 | 2 | g| |橙色| 2 |满| 17.1 | 18.5 | 1 |克| |橙色| 1 |部分| 23.4 | 22.7 | 3 | g| |葡萄| 1 |满| 23.1 | 14.1 | 3 | g| |葡萄| 2 |满| 17.2 | 17.1 | 2 | g| |葡萄| 1 |部分| 19.1 | 19.4 | 1 | g| +--------+------+----------+------------+-------------+-------+-------+ 我想添加几个专栏:

  • 一个布尔列,用于指示该测试和分析的第二个_通过值是否在所有水果类型中最高
  • 另一列列出了每个测试和分析组合中哪些水果的第二次通过值最高
使用此逻辑,我想得到下表:

+--------+------+----------+------------+-------------+-------+-------+---------+---------------------+ | fruit | test | analysis | first_pass | second_pass | order | units | highest | highest_fruits | +--------+------+----------+------------+-------------+-------+-------+---------+---------------------+ | apple | 1 | full | 12.1 | 20.1 | 2 | g | true | ["apple", "orange"] | | apple | 2 | full | 7.1 | 12.0 | 1 | g | false | ["orange"] | | apple | 1 | partial | 14.3 | 13.1 | 3 | g | false | ["orange"] | | orange | 1 | full | 19.1 | 20.1 | 2 | g | true | ["apple", "orange"] | | orange | 2 | full | 17.1 | 18.5 | 1 | g | true | ["orange"] | | orange | 1 | partial | 23.4 | 22.7 | 3 | g | true | ["orange"] | | grape | 1 | full | 23.1 | 22.1 | 3 | g | false | ["orange"] | | grape | 2 | full | 17.2 | 17.1 | 2 | g | false | ["orange"] | | grape | 1 | partial | 19.1 | 19.4 | 1 | g | false | ["orange"] | +--------+------+----------+------------+-------------+-------+-------+---------+---------------------+ +--------+------+----------+------------+-------------+-------+-------+---------+---------------------+ |水果|测试|分析|第一|通过|第二|通过|订单|单位|最高|最高|水果| +--------+------+----------+------------+-------------+-------+-------+---------+---------------------+ |苹果| 1 |满| 12.1 | 20.1 | 2 | g |真|[“苹果”,“橙色”]| |苹果| 2 |全| 7.1 | 12.0 | 1 | g |假|[“橙色”]| |苹果| 1 |部分| 14.3 | 13.1 | 3 | g |假|[“橙色”]| |橙色| 1 |满| 19.1 | 20.1 | 2 | g |真|[“苹果”,“橙色”]| |橙色| 2 |满| 17.1 | 18.5 | 1 | g |真|[“橙色”]| |橙色| 1 |部分| 23.4 | 22.7 | 3 | g |真|[“橙色”]| |葡萄| 1 |饱满| 23.1 | 22.1 | 3 | g |假|[“橙色”]| |葡萄| 2 |饱满| 17.2 | 17.1 | 2 | g |假|[“橙色”]| |葡萄| 1 |部分| 19.1 | 19.4 | 1 | g |假|[“橙色”]| +--------+------+----------+------------+-------------+-------+-------+---------+---------------------+
我是熊猫队的新手,所以我肯定我错过了一些非常简单的东西。

您可以返回
布尔值,其中
第二次通过
等于
最大值
,因为
idxmax
只返回第一次出现的
最大值

df['highest'] = df.groupby(['test', 'analysis'])['second_pass'].transform(lambda x: x == np.amax(x)).astype(bool)
然后使用
np.where
捕获所有
水果
值,这些值具有
最大值
,并
将结果合并到
数据框中,如下所示:

highest_fruits = df.groupby(['test', 'analysis']).apply(lambda x: [f for f in np.where(x.second_pass == np.amax(x.second_pass), x.fruit.tolist(), '').tolist() if f!='']).reset_index()
df =df.merge(highest_fruits, on=['test', 'analysis'], how='left').rename(columns={0: 'highest_fruit'})
最后,请继续:

first_pass = df.groupby(['test', 'analysis']).apply(lambda x: {fruit: x.loc[x.fruit==fruit, 'first_pass'] for fruit in x.highest_fruit.iloc[0]}).reset_index()
df =df.merge(first_pass, on=['test', 'analysis'], how='left').rename(columns={0: 'first_pass_highest_fruit'})
要获得:

  analysis  first_pass   fruit  order  second_pass  test units highest  \
0     full        12.1   apple      2         20.1     1     g    True   
1     full         7.1   apple      1         12.0     2     g   False   
2  partial        14.3   apple      3         13.1     1     g   False   
3     full        19.1  orange      2         20.1     1     g    True   
4     full        17.1  orange      1         18.5     2     g    True   
5  partial        23.4  orange      3         22.7     1     g    True   
6     full        23.1   grape      3         14.1     1     g   False   
7     full        17.2   grape      2         17.1     2     g   False   
8  partial        19.1   grape      1         19.4     1     g   False   

     highest_fruit             first_pass_highest_fruit  
0  [apple, orange]  {'orange': [19.1], 'apple': [12.1]}  
1         [orange]                   {'orange': [17.1]}  
2         [orange]                   {'orange': [23.4]}  
3  [apple, orange]  {'orange': [19.1], 'apple': [12.1]}  
4         [orange]                   {'orange': [17.1]}  
5         [orange]                   {'orange': [23.4]}  
6  [apple, orange]  {'orange': [19.1], 'apple': [12.1]}  
7         [orange]                   {'orange': [17.1]}  
8         [orange]                   {'orange': [23.4]} 

我想你是说

“测试”:[1,2,3,1,2,3,1,2,3]

要生成第一列,您可以按测试编号分组,并将每一秒的及格分数与最高分数进行比较:

df['highest'] = df['second_pass'] == df.groupby('test')['second_pass'].transform('max')
对于第二部分,我没有一个干净的解决方案,但这里有一个有点丑陋的解决方案,首先将索引设置为水果:

df = df.set_index('fruit')
接下来,找到每个测试中“highest”设置为True的行,并返回这些行的索引列表(即水果的名称):

定义一个函数来查看测试编号,然后返回我们刚刚生成的相应max_结果:

def max_fruits(test_num):

    if test_num == 1:
    return test1_max_fruits

    if test_num == 2:
    return test2_max_fruits

    if test_num == 3:
    return test3_max_fruits
创建列并将此函数应用于“测试”列:

df['highest_fruits'] = df['test'].apply(max_fruits)

希望我能进一步帮忙,但现在忙得不可开交。在我的脑海中,
g=df.groupby(['test','analysis'])['second_pass'].agg('idxmax')
将为您提供按
test
analysis
分组的具有最大值的行的索引。我现在不知道它是否能检测到联系。作为后续问题,有没有一种方法可以根据最高的结果将第一个传递值拉到一个新列中。例如,葡萄的全面分析和测试1(idx:6)将[苹果、橙子]作为最高的水果。如果我想使用该测试/分析组合(结果为[12.1,19.1])将apple和orange的第一个传递值拉到一个新列中,有没有办法?如此强大的模块。谢谢Stefan!
def max_fruits(test_num):

    if test_num == 1:
    return test1_max_fruits

    if test_num == 2:
    return test2_max_fruits

    if test_num == 3:
    return test3_max_fruits
df['highest_fruits'] = df['test'].apply(max_fruits)