Pandas【数据操作】

第N高的薪水

题目来源:177. 第N高的薪水 - 力扣(LeetCode)

Employee表:

image-20230804115424897

查询 Employee 表中第 n 高的工资。如果没有第 n 个最高工资,查询结果应该为 null

查询结果格式如下所示。

示例:

image-20230804115535239

题解:

参考:177. 第N高的薪水 - 力扣(LeetCode)

首先对薪水进行去重操作,使用drop_duplicates()

然后判断剩余的列长度是否大于等于N,如果不是的话就意味着不存在第N高的薪水

接下来对薪水进行降序排列,使用sort_values并将ascending设置为false,然后取出前N项,返回前N项的最后一项。

import pandas as pd

def nth_highest_salary(employee: pd.DataFrame, N: int) -> pd.DataFrame:
    df = employee[["salary"]].drop_duplicates()
    if(len(df) < N):
        return pd.DataFrame({'getNthHighestSalary(2)': [None]})
    return df.sort_values("salary", ascending=False).head(N).tail(1)

第二道题是获得第二高的薪水,大致思路和第N高的一致

import pandas as pd

def second_highest_salary(employee: pd.DataFrame) -> pd.DataFrame:
    employee = employee.drop_duplicates(["salary"])
    if len(employee["salary"].unique()) < 2:
        return pd.DataFrame({"SecondHighestSalary" :[np.NaN]})

    employee = employee.sort_values("salary", ascending=False)

    employee.drop("id", axis = 1, inplace = True)

    employee.rename({"salary": "SecondHighestSalary"}, axis = 1, inplace = True)

    return employee.head(2).tail(1)

部门工资最高的员工

题目来源:184. 部门工资最高的员工 - 力扣(LeetCode)

Employee表:

image-20230804124844418

Department表:

image-20230804124916387

查找出每个部门中薪资最高的员工。
任意顺序 返回结果表。
查询结果格式如下例所示。

示例:

image-20230804124940775

题解:

参考:184. 部门工资最高的员工 - 力扣(LeetCode)

首先通过合并两个表来获得所有的部门名称、员工名称和薪水。

image-20230804180903114

在合并后,原始表中具有相同名称的列(例如 name)会被重命名(作为 name_xname_y),因此我们需要进行列重命名。

image-20230804180940458

接下来,我们根据 Department 列对 df 进行分组,并对 Salary 列应用 transform(‘max’) 函数,这将为每个部门计算最高薪水,并返回一个与原 DataFrame 长度相同的 Series,其中每个值都是对应部门的最高薪水(它不一定是对应员工的薪水)。

0    90000
1    90000
2    80000
3    80000
4    90000
Name: Salary, dtype: int64

然后使用df[df['Salary'] == max_salary],可以选择所有薪水等于各自部门最高薪水的员工。

image-20230804181822784

import pandas as pd

def department_highest_salary(employee: pd.DataFrame, department: pd.DataFrame) -> pd.DataFrame:
    # 合并表以及重命名
    df = employee.merge(department, left_on='departmentId', right_on='id', how='left')
    df.rename(columns={'name_x': 'Employee', 'name_y': 'Department', 'salary': 'Salary'}, inplace=True)
    
    # 选择工资等于部门最高工资的员工
    max_salary = df.groupby('Department')['Salary'].transform('max')
    df = df[df['Salary'] == max_salary]
    
    return df[['Department', 'Employee', 'Salary']]

分数排名

题目来源:178. 分数排名 - 力扣(LeetCode)

题目:

Scores表:

image-20230806122914270

查询并对分数进行排序。排名按以下规则计算:

  • 分数应按从高到低排列。
  • 如果两个分数相等,那么两个分数的排名应该相同。
  • 在排名相同的分数后,排名数应该是下一个连续的整数。换句话说,排名之间不应该有空缺的数字。

score 降序返回结果表。

查询结果格式如下所示。

示例:

image-20230806122943560

题解:

参考:178. 分数排名 - 力扣(LeetCode)

理想情况下的做法是根据分数来对行进行分组,为每个组的成员分配相同的排名,但是传统的聚合函数使用依赖于将查询行分组到单个结果行中,但这道题是需要以所有行的排名方式来返回结果

例如对于示例输入,传统的聚合函数会给出以下的结果:

image-20230806123548169

但是我们需要得到所有的行:

image-20230806123611780

Pandas 提供了函数 rank() 来帮助计算沿轴的数值数据排名,我们可以将方法参数 method 设置为 dense 来分配密集排名。密集排名意味着当存在并列的值时,下一个排名不会跳过。相反,所有并列的分数都被分配相同的排名,并且下一个排名递增一。这确保排名没有间隙,并且每个分数获得唯一的排名,这也正是问题所需的。

import pandas as pd

def order_scores(scores: pd.DataFrame) -> pd.DataFrame:
    scores['rank'] = scores['score'].rank(method='dense', ascending=False)
    return scores[['score', 'rank']].sort_values('score', ascending=False)

删除重复的电子邮箱

题目来源:196. 删除重复的电子邮箱 - 力扣(LeetCode)

题目:

Person表:

image-20230806125101953

删除 所有重复的电子邮件,只保留一个具有最小 id 的唯一电子邮件。

(对于 SQL 用户,请注意你应该编写一个 DELETE 语句而不是 SELECT 语句。)

(对于 Pandas 用户,请注意你应该直接修改 Person 表。)

运行脚本后,显示的答案是 Person 表。驱动程序将首先编译并运行您的代码片段,然后再显示 Person 表。Person 表的最终顺序 无关紧要

返回结果格式如下示例所示。

示例:

image-20230806125150140

题解:

参考:196. 删除重复的电子邮箱 - 力扣(LeetCode)

要求是保留每个唯一电子邮件地址对应的最小 id。自然地,我们可以考虑使用 groupby方法来实现这一点。Person.groupby('email') 将根据 email 列中的唯一值对 Person进行分组。我们根据email列中的唯一值将Person分成多个组。这种分组允许我们将具有相同email的行分组在一起,以便我们可以分别对每个组进行操作。

我们想要找到每个组内的最小id值,以保留具有最小id的行。为了实现这一点,我们使用transform('min')方法为每个组生成一个新的Series,其中包含各自组内id列中的最小值。

image-20230806125611060

import pandas as pd

# Modify Person in place
def delete_duplicate_emails(person: pd.DataFrame) -> None:
    min_id = person.groupby('email')['id'].transform('min')
    removed_person = person[person['id'] != min_id]
    person.drop(removed_person.index, inplace=True)
    return

每个产品在不同商店的价格

题目来源:1795. 每个产品在不同商店的价格 - 力扣(LeetCode)

Products表:

image-20230806132423334

请你重构 Products 表,查询每个产品在不同商店的价格,使得输出的格式变为(product_id, store, price) 。如果这一产品在商店里没有出售,则不输出这一行。

输出结果表中的 顺序不作要求

查询输出格式请参考下面示例。

示例:

image-20230806132519428

题解:

参考:1795. 每个产品在不同商店的价格 - 力扣(LeetCode)

Pandas中的melt()方法可以将 DataFrame 从宽格式(wide format)转换为长格式(long format),并可以选择保留标识符。我们可以指定要堆叠的列及其对应的名称,从而更轻松地处理单个操作中的大量列。

id_vars 表示用作标识符变量的列,这里是 product_idvalue_vars 表示要进行堆叠的列。var_name='store' 表示包含 value_vars 的列将被命名为 storevalue_name='price' 表示’值’的列将被命名为 price

import pandas as pd

def rearrange_products_table(products: pd.DataFrame) -> pd.DataFrame:
    df = products.melt(id_vars = 'product_id', value_vars = ['store1', 'store2', 'store3'], var_name = 'store', value_name = 'price')
    df = df.dropna(axis=0)
    return df
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值