如何在熊猫中获得与 cume_dist 等效的 SQL?

Posted

技术标签:

【中文标题】如何在熊猫中获得与 cume_dist 等效的 SQL?【英文标题】:How to get SQL equivalent of cume_dist in pandas? 【发布时间】:2020-07-21 14:08:32 【问题描述】:

我尝试了不同的 pandas 方法,例如 rank、qcut、quantile,但无法获得与cume_dist() 等效的 SQL。如何在 pandas 中得到以下结果?

用SQL解决的完整问题可以在这个网站找到:https://www.windowfunctions.com/questions/ranking/4

设置

import numpy as np
import pandas as pd

df = pd.DataFrame('name': ['Molly', 'Ashes', 'Felix', 'Smudge', 'Tigger', 'Alfie', 'Oscar', 'Millie', 'Misty', 'Puss', 'Smokey', 'Charlie'],
          'breed': ['Persian', 'Persian', 'Persian', 'British Shorthair', 'British Shorthair', 'Siamese', 'Siamese', 'Maine Coon', 'Maine Coon', 'Maine Coon', 'Maine Coon', 'British Shorthair'],
          'weight': [4.2, 4.5, 5.0, 4.9, 3.8, 5.5, 6.1, 5.4, 5.7, 5.1, 6.1, 4.8],
          'color': ['Black', 'Black', 'Tortoiseshell', 'Black', 'Tortoiseshell', 'Brown', 'Black', 'Tortoiseshell', 'Brown', 'Tortoiseshell', 'Brown', 'Black'],
          'age': [1, 5, 2, 4, 2, 5, 1, 5, 2, 2, 4, 4])

cume_dist 的 SQL 代码

select name, weight, ntile(4) over ( order by weight) as weight_quartile from cats order by weight

必需的输出(sql给出了这个,在pandas中怎么做?)

此处给出的 SQL 实现:https://www.windowfunctions.com/questions/ranking/4
name    weight  percent
Tigger  3.8 8
Molly   4.2 17
Ashes   4.5 25
Charlie 4.8 33
Smudge  4.9 42
Felix   5.0 50
Puss    5.1 58
Millie  5.4 67
Alfie   5.5 75
Misty   5.7 83
Oscar   6.1 100
Smokey  6.1 100

问题:如何在 Pandas 中执行此操作?

有什么方法可以只使用 numpy 和 pandas 吗?

【问题讨论】:

为什么你不使用 spark-sql ?如果您使用的是 Spark @dsk 这不是大数据,我没有使用 Spark。 Pandas 有很多功能,我相信这可以使用 pandas 来实现。 好的 - 如果你真的想得到 Pandas DF,我建议你在 PySpark 或 Spark SQL 中完成计算,然后将 Spark DF 转换为 Pandas DF:# Spark to Pandas df_pd = df.toPandas() # Pandas 到 Spark df_sp = spark_session.createDataFrame(df_pd) 【参考方案1】:

这是一个 Python (PySpark) 版本:

import pyspark.sql.functions as F
from pyspark.sql import Window

# Define two windows for cumulating weight
win = Window().orderBy('weight') # rolling sum window
win2 = Window().orderBy(F.lit(1)) # total sum window

# get cumulative distribution
df = df.withColumn('cume_dist', F.sum('weight').over(win)*100./F.sum('weight').over(win2))

【讨论】:

这为倒数第三个条目 Molly 提供了值 80,但是,它应该是 83。 嗯好吧奇怪我去看看【参考方案2】:

创建火花df

schema = StructType([
    StructField('name', StringType(), True),
    StructField('breed', StringType(), True),
    StructField('weight', DoubleType(), True),
    StructField('color', StringType(), True),
    StructField('age', IntegerType(), True),
])

sdf = sqlContext.createDataFrame(df, schema)
sdf.createOrReplaceTempView("cats")

在 spark df 中使用 sql 函数

from pyspark.sql.window import Window
from pyspark.sql.functions import cume_dist

w = Window.orderBy(sdf['weight'])

sdf.select("weight", (cume_dist().over(w) * 100).cast(
    IntegerType()).alias("percentile")).show()

输出

+------+----------+
|weight|percentile|
+------+----------+
|   3.8|         8|
|   4.2|        16|
|   4.5|        25|
|   4.8|        33|
|   4.9|        41|
|   5.0|        50|
|   5.1|        58|
|   5.4|        66|
|   5.5|        75|
|   5.7|        83|
|   6.1|       100|
|   6.1|       100|
+------+----------+

【讨论】:

以上是关于如何在熊猫中获得与 cume_dist 等效的 SQL?的主要内容,如果未能解决你的问题,请参考以下文章

如何在熊猫数据框中对字符串进行排序或检查等效性而不考虑顺序?

如何使用熊猫查找重复名称?

如何在熊猫中获得连续滚动平均值?

如何在熊猫中获得 False 的计数 [重复]

我可以获得与 DateTime.Now.Ticks 等效的 VBA 吗?

如何在熊猫中获得多级 x 轴标记图?