【问题标题】:Choose a month of a year to rank then give resulting ranks to the rest years选择一年中的一个月进行排名,然后将结果排名分配给其余年份
【发布时间】:2016-02-06 04:15:17
【问题描述】:

样本数据:

df1 <- data.frame(id=c("A","A","A","A","B","B","B","B"),
                        year=c(2014,2014,2015,2015),
                        month=c(1,2),
                        new.employee=c(4,6,2,6,23,2,5,34))

  id year month new.employee
1  A 2014     1            4
2  A 2014     2            6
3  A 2015     1            2
4  A 2015     2            6
5  B 2014     1           23
6  B 2014     2            2
7  B 2015     1            5
8  B 2015     2           34

期望的结果:

desired_df <- data.frame(id=c("A","A","A","A","B","B","B","B"),
                        year=c(2014,2014,2015,2015),
                        month=c(1,2),
                        new.employee=c(4,6,2,6,23,2,5,34),
                        new.employee.rank=c(1,1,2,2,2,2,1,1))

  id year month new.employee new.employee.rank
1  A 2014     1            4                 1
2  A 2014     2            6                 1
3  A 2015     1            2                 2
4  A 2015     2            6                 2
5  B 2014     1           23                 2
6  B 2014     2            2                 2
7  B 2015     1            5                 1
8  B 2015     2           34                 1

排名规则是:我选择每年的第2个月对A和B之间的新员工数量进行排名。然后我需要将这些排名赋予第1个月。即每年的第1个月排名必须等于月份同年排名第2。

我尝试了这些代码来获得每个月和每年的排名,

library(data.table)
df1 <- data.table(df1)
df1[,rank:=rank(new.employee), by=c("year","month")]

如果(任何人都可以在列中滚动排名值以将月份 1 的排名替换为月份 2 的排名),这可能是一个解决方案。

【问题讨论】:

    标签: r data.table conditional-statements rank


    【解决方案1】:

    您已经尝试了data.table 解决方案,那么我将如何使用data.table 进行此操作

    library(data.table) # V1.9.6+
    temp <- setDT(df1)[month == 2L, .(id, frank(-new.employee)), by = year]
    df1[temp, new.employee.rank := i.V2, on = c("year", "id")]
    df1
    #    id year month new.employee new.employee.rank
    # 1:  A 2014     1            4                 1
    # 2:  A 2014     2            6                 1
    # 3:  A 2015     1            2                 2
    # 4:  A 2015     2            6                 2
    # 5:  B 2014     1           23                 2
    # 6:  B 2014     2            2                 2
    # 7:  B 2015     1            5                 1
    # 8:  B 2015     2           34                 1
    

    它看起来有点类似于上面的dplyr 解决方案。这基本上是每年对ids 进行排名,并将它们加入原始数据集。我在这里使用data.table V1.9.6+。

    【讨论】:

    • 不错的解决方案。请您简要解释一下为什么我们在 2 之后使用“L”和“i”。在 V2 之前,最后一个是格式 .(id, ...)。对不起,我是新手。非常感谢
    • @David 你能帮我在这种情况下创建用户定义的函数吗?我正在尝试对许多项目进行排名。我认为这个函数有点像这个函数(df,item_to_rank)。我试过了,但我什至无法返回因子“temp”。你能帮我嵌套成功的命令吗?非常感谢
    • 当您准确描述您的需求时,在链接此问题时发布一个新问题是值得的。基于cmets我帮不了你。
    • 我想我在新问题上帮助了你,但没有收到你的任何反馈。
    • 亲爱的大卫,我目前正在重新安装我的窗口,所以我没有机会查看新帖子。而且我不知道为什么没有关于这篇文章的通知电子邮件。非常感谢,我会尽快提供反馈。
    【解决方案2】:

    这是一个基于dplyr 的解决方案。这个想法是将数据减少到您想要比较的部分,进行比较,然后将结果连接回原始数据集,将其扩展以填充所有相关插槽。请注意为创建示例数据对代码所做的编辑。

    df1 <- data.frame(id=c("A","A","A","A","B","B","B","B"),
                            year=rep(c(2014,2014,2015,2015), 2),
                            month=rep(c(1,2), 4),
                            new.employee=c(4,6,2,6,23,2,5,34))
    
    library(dplyr)
    
    df1 %>%
      # Reduce the data to the slices (months) you want to compare
      filter(month==2) %>%
      # Group the data by year, so the comparisons are within and not across years
      group_by(year) %>%
      # Create a variable that indicates the rankings within years in descending order
      mutate(rank = rank(-new.employee)) %>%
      # To prepare for merging, reduce the new data to just that ranking var plus id and year
      select(id, year, rank) %>%
      # Use left_join to merge the new data (.) with the original df, expanding the
      # new data to fill all rows with id-year matches
      left_join(df1, .) %>%
      # Order the data by id, year, and month to make it easier to review
      arrange(id, year, month)
    

    输出:

    Joining by: c("id", "year")
      id year month new.employee rank
    1  A 2014     1            4    1
    2  A 2014     2            6    1
    3  A 2015     1            2    2
    4  A 2015     2            6    2
    5  B 2014     1           23    2
    6  B 2014     2            2    2
    7  B 2015     1            5    1
    8  B 2015     2           34    1
    

    【讨论】:

    • 亲爱的 ulfelder,它适用于我的示例,但我无法将其转化为我的真实案例,因为我是新手。我无法理解您的所有语法。不过,我非常感激。我会在另一天回复你的建议。现在我将首先使用 data.table 方法。
    • 如果有帮助,我会添加一些 cmets 来解释每个步骤的作用。
    猜你喜欢
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多