【问题标题】:Make SQL case when return column and group in Pandas在 Pandas 中返回列和组时制作 SQL 案例
【发布时间】:2021-12-25 00:14:07
【问题描述】:

我的数据集的 sn-p 如下所示:

User_id | Search_id | Price | score | clicked | company | rank
1       | 1         | 10    | 7.3   | 0       | other   | 3
1       | 1         | 8     | 10.0  | 1       | other   | 2
1       | 1         | 7.5   | 10.0  | 1       | us      | 1
2       | 2         | 7     | 10.0  | 0       | us      | 3
2       | 2         | 6.5   | 10.0  | 1       | other   | 2
2       | 2         | 4     | 6.5   | 1       | other   | 1

我使用的 SQL 查询类似于:

proc sql;

create table File1_Real as

select User_ID
,      Search_ID  
,      mean(case when company = 'us' then rank else . end) as Our_Rank
,      mean(case when company = 'us' then Price else . end) as Our_Price
,      mean(case when company = 'us' then score else . end) as Our_Score
,      mean(case when company = 'us' then clicked else . end) as Our_Click
,      mean(case when rank <= 5 then price else . end) as Price_Top5
,      mean(case when Rank =  BestClickRank then price else . end) as Top_Price
,      mean(case when Rank =  BestClickRank then case when score= 10 then 1 else 0 end else . end) as Top_is10
,      mean(BestClickRank) as Top_Rank    
,      min(price) as Min_Price
,      count(*) as QuotesReturned
,      sum(case when price < 7.5 then 1 else 0 end) as QuotesLT75
,      mean(case when price < 7.5 then Score else 0 end) as LT75_Score
,      sum(clicked) as TotalClicks

from (
Select *
,      min(case when Clicked = 1 then Rank else . end) as BestClickRank

from work.data
where score = 10
group by user_id, search_id)
Group by 1,2
quit;

预期的输出类似于:

    User_id | Search_id | Our_Rank| Our_Price | Our_Score | Our_Click | Price_Top5 | Top_Price | Top_is10 | Top_Rank | Min_Price | QuotesReturned | QuotesLT75 |  LT75_Score | TotalClicks 
        1   | 1         | 1       | 7.5       | 10.0      | 1         | 7.75       | 7.5       | 1        | 1        | 7.5       | 2              | 0         | 0           | 2
        2   | 2         | 3       | 7         | 10.0      | 0         | 5.8       | 6.5        | 1       | 2         | 6.5       | 2              | 0          | 0          | 1
 
    

我尝试过这样的事情:

df[(df['company']!='us')].groupby(['User_id','Search_id']).agg({'price':['min','mean']})

但是:1) 它不返回其余列,并且 2) 我不确定如何进行计算以返回另一列中的值,例如 Our_Rank

有没有可能一起做这一切? 我无权访问 SQL-pandas 包,因此只能使用 pandas。

【问题讨论】:

  • 你的预期输出是什么?
  • @not_speshal 刚刚添加 :)

标签: python sql pandas


【解决方案1】:

IIUC,你想要这样的东西:

def f(x):
    d = dict()
    BestClickRank = x["rank"].where(df["clicked"]==1).min()
    d["Price_Top5"] = x["Price"].where(x["rank"].le(5)).mean()
    d["Top_Price"] = x["Price"].where(df["rank"].eq(BestClickRank)).mean()
    d["Top_is10"] = x["score"].where(x["rank"].eq(BestClickRank)).dropna().eq(10).mean()
    d["Top_Rank"] = BestClickRank.mean()
    d["LT75_Score"] = x["score"].where(x["Price"].lt(7.5)).mean()
    return pd.Series(d)

df = data[data["score"].eq(10)]
table1 = df[df["company"].eq("us")].groupby(["User_id", "Search_id"]).agg(Our_rank=("rank","mean"),
                                                                          Our_Price=("Price","mean"),
                                                                          Our_Score=("score","mean"),
                                                                          Our_Click=("clicked","mean"))

table2 = df.groupby(["User_id", "Search_id"]).agg(Min_Price=("Price", "min"),
                                                  Quotes_Returned=("Price","size"),
                                                  QuotesLT75=("Price", lambda x: x.lt(7.5).sum()),
                                                  TotalClicks=("clicked", "sum"))

table3 = df.groupby(["User_id", "Search_id"]).apply(f)
output = pd.concat([table1, table2, table3], axis=1)

>>> output

                   Our_rank  Our_Price  Our_Score  Our_Click  Min_Price  Quotes_Returned  QuotesLT75  TotalClicks  Price_Top5  Top_Price  Top_is10  Top_Rank  LT75_Score
User_id Search_id                                                                                                                                                       
1       1               1.0        7.5       10.0        1.0        7.5                2           0            2        7.75        7.5       1.0       1.0         NaN
2       2               3.0        7.0       10.0        0.0        6.5                2           2            1        6.75        6.5       1.0       2.0        10.0
输入数据:
data = pd.DataFrame({"User_id": list(map(int, "111222")),
                     "Search_id": list(map(int, "111222")),
                     "Price": [10,8,7.5,7,6.5,4],
                     "score": [7.3,10,10,10,10,6.5],
                     "clicked": list(map(int, "011011")),
                     "company": ["other", "other", "us", "us", "other", "other"],
                     "rank": list(map(int, "321321")),
                     })

【讨论】:

  • 我认为这是解决问题的好方法! Price_top5Min_Price(4.0 与 6.5)的区别在于,在底部的 SQL 查询中,您会看到它全部通过 score = 10 过滤,因此 Min_Price 的计算将是最小的价格在所有得分为 10 的搜索中。我们如何将其添加到此案例中?
  • 实际上其他几列也是如此
  • 我编辑它以过滤分数 = 10,但仍然没有得到您的确切输出(Price_Top5Quotes_LT75LT75_score 中的差异)。请记住,未来的问题是用文字解释逻辑,而不是用另一种语言编写代码。 SO 并不意味着成为语言之间的翻译。但是,您可以将上述答案用作您需要的基本结构并根据需要进行调整。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-26
  • 2011-11-20
相关资源
最近更新 更多