【问题标题】:Re-ordering and appending an additional column to .SD output重新排序并将附加列附加到 .SD 输出
【发布时间】:2017-03-03 04:55:29
【问题描述】:

我想将标量函数(如mean)应用于主要组,并在次要组中对值进行排名。这是我正在尝试做的示例代码:

library(data.table)
mytestdata <- data.table(name=c("tom","john","tom","john","jim","jim","jack"),
                         len=c(10,15,12,23,3,12,3),
                         group=c("a","b","a","a","a","b","b"))
mytestdata[, .SD[, .(mean(len), .N), by="name"][order(V1)], by = "group"]  # I need the .N to log

这里的输出是我想要的。但是,当我尝试对每个组中的名称进行排名时,我无法获得所需的输出。

mytestdata[, .SD[, .(mean(len), .N), by="name"][order(V1), myrank := seq(1:.N)], by = "group"]

上面的代码正确地分配了排名,但将列重新排序为默认顺序(忽略order(V1),它在上一行中起作用)。我认为这与:= 不显示输出有关。有没有办法解决这个问题?

我尝试了类似的东西

mytestdata[, .(.SD[, .(mean(len), .N), by="name"][order(V1)], seq(1:.N), by = "group"]

但它会抛出一个错误,说明在j 中错误地使用了list() 方法。

编辑:我想要的输出是(排名应该在组内)(A)

   group name V1 N myrank
1:     a  jim  3 1    1
2:     a  tom 11 2    2
3:     a john 23 1    3
4:     b jack  3 1    1
5:     b  jim 12 1    2
6:     b john 15 1    3

编辑:为了澄清我的观点,我的原始代码,

mytestdata[, .SD[, .(mean(len), .N), by="name"][order(V1)], by = "group"]

返回按我想要的方式排序的数据表,即 (1)

   group name V1 N
1:     a  jim  3 1
2:     a  tom 11 2
3:     a john 23 1
4:     b jack  3 1
5:     b  jim 12 1
6:     b john 15 1

现在,我想保持这种顺序并为每个组中的名称分配等级。由于i 在data.table 中的j 之前被评估,我可以在与上面order() 相同的语句中分配排名,即,

mytestdata[, .SD[, .(mean(len), .N), by="name"][order(V1), myrank := 1:.N], by = "group"]

这会正确分配排名,即 (2)

   group name V1 N myrank
1:     a  tom 11 2      2
2:     a john 23 1      3
3:     a  jim  3 1      1
4:     b john 15 1      3
5:     b  jim 12 1      2
6:     b jack  3 1      1

但是,行的顺序不再与 (1) 中的相同,因为我猜是赋值运算符抑制了输出并以无序格式存储数据表。现在,要获得 (A) 形式的输出,我必须通过再次分组来重新排序行在链接方法中分配排名列,即,

mytestdata[, .SD[, .(mean(len), .N), by="name"][order(V1), myrank := 1:.N], by = "group"][order(rank), .SD, by = "group"]

(或)

mytestdata[, .SD[, .(mean(len), .N), by="name"][order(V1)], by = "group"][, myrank := 1:.N, by = "group"]

这给出了所需的输出 (A)。虽然这两个都解决了我的问题,但我很好奇是否有一个解决方案可以消除额外的链接,因为在 (2) 中正确分配了等级,并且在 (2) 中的顺序已经正确强>(1).

【问题讨论】:

  • 我认为你只是把它放在错误的地方 - 你只是想要mytestdata[, .SD[, .(mean(len), .N), by=name][order(V1)], by=group][, rank := 1:.N, by=group][] 吗?
  • 是的,这行得通。谢谢!有没有办法消除额外的分组只是为了排名?具体来说,我很好奇为什么order(V1) 在第一种情况下有效,但在第二种情况下似乎没有显示重新排序的行,而是在重新排序后分配排名但以原始顺序显示它们。跨度>
  • 嗯....我还没有看到如何避免它。让我想想
  • mytestdata[, .(mean_len = mean(len), .N, group, len), by="name"][i = order(mean_len), j = .( name, len, mean_len, rank = 1:.N), by = c("group")]
  • 上面代码的问题是它不会处理名字的关系

标签: r data.table


【解决方案1】:

我认为您在处理[.data.table 的 i 和 j 参数的顺序方面遇到了问题;

这是我认为你确实想要的,尽管你实际上只提供了你不想要的细节:

mytestdata[, .SD[, .(mean(len), .N), by="name"]][order(V1),][,rank := rank(V1)][]
   name   V1 N rank
1: jack  3.0 1    1
2:  jim  7.5 2    2
3:  tom 11.0 2    3
4: john 19.0 2    4

当关系问题出现时,我搜索:

> ?rank   # Turns out there is a data.table function for that as well, `frank`

> mytestdata[, .SD[, .(mean(len), .N), by="name"]][order(V1),][,rank := frank(V1)][]
   name   V1 N rank
1: jack  3.0 1    1
2:  jim  7.5 2    2
3:  tom 11.0 2    3
4: john 19.0 2    4

排序(首先)和排名计算(稍后)的单独应用似乎是需要的。如果你想要一种不同的计算排名的方法,frank 函数有:ties.method=c("average", "first", "random", "max", "min", "dense")[] 终端的使用是我刚刚从@thelatemail 学到的。最后的评论。我会让列名更“特别”。使用“rank”之类的列名称会使习惯于将其视为函数名称的用户感到困惑。最好将其设为“myrank”或“testrank”。

回应下面的评论:我仍然很难准确地理解想要什么(特别是不想要“最后的额外分组”是什么意思),但如果希望根据“新”排名重新排序,那么为什么不:

 mytestdata[, .SD[, .(mean(len), .N), by=name][order(V1)], by=group][ #
                       , myrank := frank(V1), by=group][order(myrank), ]
   group name V1 N myrank
1:     a  jim  3 1      1
2:     b jack  3 1      1
3:     a  tom 11 2      2
4:     b  jim 12 1      2
5:     a john 23 1      3
6:     b john 15 1      3

【讨论】:

  • mytestdata[, .SD[, .(mean(len), .N), by="name"]]mytestdata[, .(mean(len), .N), by="name"]不一样吗?
  • @42- 感谢您的回答!我用预期的答案更新了我的问题。我实际上对group 中的myrank 感兴趣,因此如果name 出现在多个组中,它可以在答案中出现多次。
  • @thelatemail 的答案是我正在寻找的,但我很好奇是否有办法避免最后的额外分组。我意识到首先计算i 中的排序,然后myrank 下一个由group 分配myrank,我正在寻找一种方法来显示该排序输出以及分配本身,因为是我需要的(按等级排序)。如果没有分配,代码将按预期工作,并且顺序正确。但是当分配发生时,排序不会“显示”而只是“存储”,如果这有意义的话。我正在努力解决这个问题。
  • @42- 请参阅我的第二次编辑,我详细描述了我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-28
  • 1970-01-01
  • 2017-03-20
  • 2014-08-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多