【问题标题】:Sort a factor based on value in one or more other columns根据一个或多个其他列中的值对因子进行排序
【发布时间】:2012-06-01 06:17:27
【问题描述】:

我浏览了许多关于排序因素的帖子,但还没有找到适合我的问题的匹配项。不幸的是,我对 R 的了解还很初级。

我有一个正在使用的考古文物目录的子集。我正在尝试对诊断历史工件类型和站点测试位置进行交叉制表。使用 ddply 或 tapply 很容易。

我的问题是我想按平均诊断日期(数字/年份)对工件类型(一个因素)进行排序,并且我一直按字母顺序获取它们。我知道我需要将其设为有序因子,但无法弄清楚如何按另一列中的年份值对其进行排序。

IDENTIFY                                      MIDDATE
engine-turned fine red stoneware              1769
white salt-glazed stoneware, scratch blue     1760
wrought nail, 'L' head                        1760
yellow lead-glazed buff earthenware           1732
...

需要订购的:

IDENTIFY                                      MIDDATE
yellow lead-glazed buff earthenware           1732
white salt-glazed stoneware, scratch blue     1760
wrought nail, 'L' head                        1760
engine-turned fine red stoneware              1769
...

因子 (IDENTIFY) 需要按日期 (MIDDATE) 排序。我以为我有它

Catalog$IDENTIFY<-factor(Catalog$IDENTIFY,levels=Catalog$MIDDATE,ordered=TRUE)

但得到警告:

In `levels<-`(`*tmp*`, value = if (nl == nL) as.character(labels) 
else paste0(labels,: duplicated levels will not be allowed 
in factors anymore

IDENTIFY 有大约 130 个因子水平,其中许多具有相同的 MIDDATE 值,所以我需要按 MIDDATE 和另一列 TYPENAME 订购 IDENTIFY。

更多细节:

我有一个数据框Catalog,它分解为(即str(Catalog)):

> str(Catalog)
'data.frame':   2211 obs. of  15 variables:
 $ TRENCH  : Factor w/ 7 levels "DRT 1","DRT 2",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ U_TYPE  : Factor w/ 3 levels "EU","INC","STP": 1 1 1 1 1 1 1 1 1 1 ...
 $ U_LBL   : Factor w/ 165 levels "001","005","007",..: 72 72 72 72 72 72 ...
 $ L_STRAT : Factor w/ 217 levels "#2-7/25","[3]",..: 4 4 4 4 4 4 89 89 89 89 ...
 $ START   : num  0 0 0 0 0 0 39.4 39.4 39.4 39.4 ...
 $ END     : num  39.4 39.4 39.4 39.4 39.4 39.4 43.2 43.2 43.2 43.2 ...
 $ Qty     : int  1 1 3 5 1 1 6 8 1 1 ...
 $ MATNAME : Factor w/ 6 levels "Ceramics","Chipped Stone",..: 1 1 1 5 5 6 ...
 $ TYPENAME: Factor w/ 9 levels "Architectural Hardware",..: 9 9 9 1 1 3 9 ...
 $ CATNAME : Factor w/ 32 levels "Biface","Bottle Glass",..: 24 29 29 6 24 ...
 $ IDENTIFY: Factor w/ 112 levels "amethyst bottle glass",..: 17 91 96 71 103 ...
 $ BEGDATE : int  1820 1820 1830 1835 1700 NA 1670 1762 1800 1720 ...
 $ ENDDATE : int  1900 1970 1860 1875 1820 NA 1795 1820 1820 1780 ...
 $ OCC_LBL : Ord.factor w/ 5 levels "Late 19th Century"<..: 2 1 2 2 4 5 4 3 ...
 $ MIDDATE : num  1860 1895 1845 1855 1760 ...

我需要将IDENTIFY 设为有序因子,并按MIDDATE -> TYPENAME -> alpha 通过IDENTIFY 重新排序。

我没有真正了解的是如何通过来自多个列的组合订单重新排序。

我只会在数据库中执行此操作,但我正在运行的很多内容都是各种交叉表中的加权平均值(例如,按位置划分的工件类别的地表以下加权平均深度)...

...在 Access 中可行,但混乱且不可预测。在 R 中管理起来更容易、更干净,但我宁愿不必手动重新排序结果表。

我想要制作的是一些类似的东西:

>xtab.Catalog<-tapply(Catalog$Qty,list(Catalog$IDENTIFY,Catalog$TRENCH),sum)

IDENTIFY                        DRT1    DRT2    DRT3    DRT4    DRT5    DRT6
Staffordshire stoneware         4       NA      NA      NA      NA      NA  
undecorated delftware           6       4       NA      NA      NA      NA  
unidentified wrought nail       15      9       3       1       3       NA  
white salt-glazed stoneware     6       1       1       NA      2       1   
white salt-glazed scratch blue  1       NA      NA      NA      NA      NA  
white stoneware, slip-dipped    NA      NA      NA      NA      NA      NA  
wrought nail, 'L' head          2       NA      NA      NA      NA      NA  
wrought nail, 'rose' head       62      21      4       NA      1       1   
wrought nail, 'T' head          2       NA      1       NA      NA      1   
yellow lead-glazed              12      NA      NA      NA      1       3   
...

...但我需要它们按逻辑(即时间/类型)顺序而不是字母顺序排序。

【问题讨论】:

  • 查看统计包中的函数reorder()(即base R)。
  • 试过reorder(Catalog$IDENTIFY,Catalog$MIDDATE),但收到了关于重复关卡的相同警告,并且IDENTIFY都转向NA的...
  • 如果没有可复现的代码,帮助你有点困难。你能试着做一个可重现的例子,我来看看吗?
  • 刚刚添加了更多关于我正在做的事情的细节......为我在 R 语言中的半文盲表示歉意。一直在使用 SPSS 处理这些类型的事情,但我们的办公室停止更新它(卡在有问题的 v11 上)。
  • 一个最小的可重现示例包含任何人都可以在他们的机器上运行并获得相同错误/警告的代码。有关更多详细信息,请参阅stackoverflow.com/q/5963269/602276。无论如何,您收到的是警告,而不是错误,因此请评估您的结果,看看它实际上是否正常。

标签: r r-factor


【解决方案1】:

这是一个可重现的样本,带有解决方案:

set.seed(0)
a = sample(1:20,replace=F)
b = sample(1:20,replace=F)
f = as.factor(letters[1:20])

> a
 [1] 18  6  7 10 15  4 13 14  8 20  1  2  9  5  3 16 12 19 11 17
> b
 [1] 16 18  4 12  3  5  6  1 15 10 19 17  9 11  2  8 20  7 13 14
> f
 [1] a b c d e f g h i j k l m n o p q r s t
Levels: a b c d e f g h i j k l m n o p q r s t

现在是新因素:

fn = factor(f, levels=unique(f[order(a,b,f)]), ordered=TRUE)

> fn
 [1] a b c d e f g h i j k l m n o p q r s t
20 Levels: k < l < o < f < n < b < c < i < m < d < s < q < g < h < e < ... < j

按“a”排序,然后按“b”排序,最后按“f”本身排序(尽管在本例中,“a”没有重复值)。

【讨论】:

  • 谢谢。我会试一试,看看效果如何。我怀疑我需要从 MIDDATE 中创建一个单独的有序因子向量,但是字段的组合应该可以防止重复问题(这三个应该构成一个唯一的位置)。
  • 如果有人回答了您的问题,我建议您使用复选标记(将其涂成绿色)来表示。这是礼貌的,对未来的搜索者有很大帮助。
【解决方案2】:

我推荐以下基于 dplyr 的方法 (h/t daattali),它可以扩展到任意数量的列:

library(dplyr)
Catalog <- Catalog %>%
  arrange(MIDDATE, TYPENAME) %>%               # sort your dataframe
  mutate(IDENTIFY = factor(IDENTIFY, unique(IDENTIFY))) # reset your factor-column based on that order

【讨论】:

  • 给我以下错误:Error in levels(*tmp*, value = if (nl == nL) as.character(labels) else paste0(labels, : factor level [2] is duplicated;我在IDENTIFYTYPENAME 中肯定有重复值...这个技巧是否仅适用于唯一值列?
  • 想通了:因为IDENTIFY 有重复值,它需要unique 在级别定义中
  • 这太有用了,应该是dplyr函数。
【解决方案3】:

函数fct_reorder2 就是这样做的。

请注意fct_reorder 是按升序排序而fct_reordering2 是按降序排序的微妙之处。

文档中的代码:

df0 <- tibble::tribble(
  ~color,     ~a, ~b,
  "blue",      1,  2,
  "green",     6,  2,
  "purple",    3,  3,
  "red",       2,  3,
  "yellow",    5,  1

)

df0$color <- factor(df0$color)
fct_reorder(df0$color, df0$a, min)
 #> [1] blue   green  purple red    yellow
 #> Levels: blue red purple yellow green
fct_reorder2(df0$color, df0$a, df0$b)

【讨论】:

    【解决方案4】:

    data.table 版本。像往常一样单线

    library(data.table)
    Catalog = data.table(Catalog)
    Data[, IDENTIFY := reorder(IDENTIFY, MIDDATE)]
    

    注意:IDENTIFY 必须已经成为一个因素。这个解决方案的主要力量来自stats::reorder函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-26
      • 2017-04-06
      • 2015-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多