如何为不同行分配排名值至新列?及拆分科目分数至对应列
两个数据处理问题的解决方案
嘿,我来帮你搞定这两个日常数据整理里的常见需求,咱们一个个来拆解:
问题一:如何为不同行的排名值分配至新列?
这个需求得看你是要全局排名还是分组排名,我给你分享两种常用工具(Python pandas 和 R)的实现方式,你可以按需选择:
Python pandas 实现
假设你有一个包含person和score的数据集,想要按分数降序生成排名:
import pandas as pd # 示例数据 df = pd.DataFrame({ 'person': ['Joe', 'Ray', 'Jenny', 'Luna'], 'score': [85, 92, 78, 92] }) # 1. 全局排名(支持不同排名规则) # method可选:average(相同分数取平均)、min(相同分数取最小排名)、max(最大)、dense(连续排名)、first(按出现顺序) df['global_rank'] = df['score'].rank(ascending=False, method='dense') # 2. 分组排名(比如按班级分组后排名) # 先假设数据有class列 # df['group_rank'] = df.groupby('class')['score'].rank(ascending=False, method='dense') print(df)
R 实现
用dplyr工具包来处理:
library(dplyr) # 示例数据 df <- data.frame( person = c("Joe", "Ray", "Jenny", "Luna"), score = c(85, 92, 78, 92) ) # 1. 全局连续排名 df <- df %>% mutate(global_rank = dense_rank(desc(score))) # 2. 分组排名 # df <- df %>% group_by(class) %>% mutate(group_rank = dense_rank(desc(score))) %>% ungroup() print(df)
问题二:批量拆分科目分数至新列(高效处理多科目)
这个需求的核心是把长格式的科目-分数对转成宽格式的列,而且要自动识别所有科目,不用手动列出来,完全适配科目数量多的场景。
Python pandas 高效实现
import pandas as pd import re # 你的原始数据 df = pd.DataFrame({ 'person': ['Joe', 'Ray', 'Jenny'], 'class_score': ['gram(-),phy(+),bio(++)', 'chem(+),bio(-)', 'fin(++),db(-),pre(-)'] }) # 步骤1:拆分每个class_score条目为单独行,并提取科目和分数 # 用正则匹配科目名和括号里的分数 pattern = re.compile(r'(\w+)\((.*?)\)') # 拆分逗号分隔的条目并展开 exploded = df['class_score'].str.split(',', expand=True).stack().reset_index(level=1, drop=True).to_frame('item') # 提取科目和分数到新列 exploded[['cls', 'score']] = exploded['item'].str.extract(pattern) # 和原数据合并 merged = df.join(exploded).drop(columns=['class_score', 'item']) # 步骤2:转成宽表,自动生成所有科目列 result = merged.pivot(index='person', columns='cls', values='score').reset_index() # 去掉列名的索引,让格式更整洁 result.columns.name = None # 合并回原始的class_score列(重命名为cls_sco) result = result.merge(df[['person', 'class_score']], on='person').rename(columns={'class_score': 'cls_sco'}) # 调整列顺序,把person和cls_sco放在最前面 cols = ['person', 'cls_sco'] + [col for col in result.columns if col not in ['person', 'cls_sco']] result = result[cols] print(result)
运行后会得到你想要的输出:缺失的科目位置会自动填充NaN(对应你示例里的NA)。
R 实现(用tidyverse)
library(tidyverse) # 原始数据 df <- tibble( person = c("Joe", "Ray", "Jenny"), class_score = c("gram(-),phy(+),bio(++)", "chem(+),bio(-)", "fin(++),db(-),pre(-)") ) result <- df %>% # 拆分每个逗号分隔的条目为单独行 separate_rows(class_score, sep = ",") %>% # 提取科目和分数 extract(class_score, into = c("cls", "score"), regex = "(\\w+)\\((.*?)\\)") %>% # 转成宽表,自动生成所有科目列 pivot_wider(names_from = cls, values_from = score) %>% # 合并回原始的class_score列 left_join(df, by = "person") %>% rename(cls_sco = class_score) %>% # 调整列顺序 select(person, cls_sco, everything()) print(result)
这两种方法都是向量化操作,比循环遍历快得多,不管你有几十还是上百个科目,都能自动识别并生成对应的列,完全满足高效处理的需求。
内容的提问来源于stack exchange,提问作者user13712702
相关产品推荐
相关产品推荐

