【问题标题】:How to re-shape a league table into a different format using R?如何使用 R 将排行榜重新塑造成不同的格式?
【发布时间】:2021-07-25 00:40:53
【问题描述】:

我有一个看起来像这样的排名表(由于 netmeta 包中的 netleague 函数)(本示例中的值是为了简化它的外观):

A 0.3 (-0.4 to 0.6) .
0.1 (-0.9 to 0.3) B -0.6 (-0.9 to 0.0
0.2 (-0.8 to 0.4) 0.3 (-0.6 to 0.1) C

下面的三角形代表间接比较(我对此示例感兴趣的那些)并读取列与行。例如,0.1 (-0.9 to 0.3)A vs B

这些值作为data.frame 存储在R 的环境中list 的元素中。

结果我需要的是:

char1 char2 value1 value2 value3
A B 0.1 0.9 0.3
A C 0.2 -0.8 0.4
B A -0.1 -0.3 0.9
B C 0.3 -0.6 0.1
C A -0.2 -0.4 0.8
C B -0.3 -0.1 0.6

请注意,为了获得 B 与 A,我颠倒了这些值。根据结果​​的性质,我可能会改为使用 1/value。

我试过看at the code behind the netleague function,但揭穿它对我来说是相当先进的。

有人知道如何使用 R 自动执行此任务吗?

到目前为止,我最好的选择是手动执行此操作(耗时超过 8000 个值并且可能引入人为拼写错误)或至少使用 Excel 中的一些公式(仍然很耗时,我必须逐行调整公式)。

可重现格式的数据:(来源:dput(league[["fixed"]][1:4, ])

structure(list(V1 = c("dalia", "0.08 (-0.9 to  0.26)", 
"-0.15 (-0.40 to  0.06)", "0.37 ( 0.00 to  0.78)"), V2 = c("-0.05 (-0.33 to  0.22)", 
"camelia", "-0.24 (-0.49 to -0.01)", "0.31 (-0.09 to  0.75)"
), V3 = c("-0.14 (-0.64 to  0.32)", "-0.37 (-0.66 to -0.05)", 
"margher", "0.54 ( 0.12 to  0.95)"), V4 = c(".", ".", ".", 
"rosa_can"), V5 = c(".", ".", ".", "."), V6 = c(".", ".", ".", 
"."), V7 = c(".", ".", ".", "."), V8 = c("0.65 ( 0.54 to  0.87)", 
"0.54 ( 0.38 to  0.78)", "0.77 ( 0.2 to  1.28)", "0.29 (-0.08 to  0.67)"
), V9 = c(".", ".", ".", "."), V10 = c(".", ".", ".", "."), V11 = c(".", 
".", ".", "."), V12 = c("0.23 (-0.52 to  0.99)", ".", "-0.05 (-0.56 to  0.47)", 
"."), V13 = c(".", "0.07 (-0.25 to  0.33)", ".", ".")), row.names = c(NA, 
4L), class = "data.frame")

【问题讨论】:

  • 您能否提供可重现格式的数据?阅读how to give a reproducible example
  • @RonakShah 我已经更新了原帖 - 谢谢,我不知道dput(总是很好学习!)。

标签: r dataframe


【解决方案1】:

你可以试试:

ff <- function(x, y, z){
  sprintf("%.1f (%.1f to %.1f)",  -as.numeric(x),
          -as.numeric(z), -as.numeric(y))
}
DT <- as.matrix(DT)
rownames(DT) <- colnames(DT) <- diag(DT)

pattern <- r"((\S+)\s+\(\s*(\S+)\s*to\s*(\S+)\))"
DT[upper.tri(DT)] <- gsubfn::gsubfn(pattern,ff, t(DT)[upper.tri(DT)])

with(subset(as.data.frame.table(DT), Var1!=Var2),
cbind(Var2, Var1, read.table(text=gsub("[()to]", " ", Freq))))                          
      

 Var2 Var1   V1   V2  V3
1    A    B  0.1 -0.9 0.3
2    A    C  0.2 -0.8 0.4
3    B    A -0.1 -0.3 0.9
4    B    C  0.3 -0.6 0.1
5    C    A -0.2 -0.4 0.8
6    C    B -0.3 -0.1 0.6

【讨论】:

  • 我尝试了您的代码,它似乎几乎完美 - 但是我注意到所有已反转的值(例如 B 与 A - 我假设 ff function 包含的那些值)四舍五入到第一个小数,这导致与原始数字(A vs B)相比不同的数字(但可以说是相似的)。仍然 - 非常感谢,快到了!
  • 我检查了sprintf函数,我不知道!似乎只需键入 %.2f!
  • 我是否应该将A vs B1/V11/V21/V3 设置为V1V2V3B vs A,您会建议简单吗?修改ff函数?
  • @Raphus 是的。只需相应地调整 ff 函数
【解决方案2】:

这是您的问题的第一次尝试,但我无法完全匹配您想要的输出。 所以请指出错误,这样我就可以再打一轮了..

library(data.table)
# Sample data
DT <- fread('"A"    "0.3 (-0.4 to 0.6)"     "."
"0.1 (-0.9 to 0.3)"     "B"     "-0.6 (-0.9 to 0.0)"
"0.2 (-0.8 to 0.4)"     "0.3 (-0.6 to 0.1)"     "C"', header = FALSE)

# Code
# Get names, set as row and colnames
names.v <- diag(as.matrix(DT))
setnames(DT, new = names.v)
DT[, char2 := names.v]
#                    A                 B                  C rowname
# 1:                 A 0.3 (-0.4 to 0.6)                  .       A
# 2: 0.1 (-0.9 to 0.3)                 B -0.6 (-0.9 to 0.0)       B
# 3: 0.2 (-0.8 to 0.4) 0.3 (-0.6 to 0.1)                  C       C

# Melt to long
ans <- setcolorder(melt(DT, id.vars = "char2", variable.name = "char1"), c(2,1,3))
#    char1 char2              value
# 1:     A     A                  A
# 2:     A     B  0.1 (-0.9 to 0.3)
# 3:     A     C  0.2 (-0.8 to 0.4)
# 4:     B     A  0.3 (-0.4 to 0.6)
# 5:     B     B                  B
# 6:     B     C  0.3 (-0.6 to 0.1)
# 7:     C     A                  .
# 8:     C     B -0.6 (-0.9 to 0.0)
# 9:     C     C                  C
                
# keep relevant rows
ans <- ans[!char1 == char2, ]
# extract numeric values
ans[, paste0("val", 1:length(tstrsplit(ans$value, "[^0-9-\\.]+", perl = TRUE))) := 
      tstrsplit(ans$value, "[^0-9-\\.]+", perl = TRUE)][]
#    char1 char2              value val1 val2 val3
# 1:     A     B  0.1 (-0.9 to 0.3)  0.1 -0.9  0.3
# 2:     A     C  0.2 (-0.8 to 0.4)  0.2 -0.8  0.4
# 3:     B     A  0.3 (-0.4 to 0.6)  0.3 -0.4  0.6
# 4:     B     C  0.3 (-0.6 to 0.1)  0.3 -0.6  0.1
# 5:     C     A                  .    . <NA> <NA>
# 6:     C     B -0.6 (-0.9 to 0.0) -0.6 -0.9  0.0

【讨论】:

  • 嗨@Wimpel,谢谢!输出几乎就在那里(太棒了!!!),但我认为您的代码也使用了上三角形的值。例如,您的 B - A 组合是 0.3 -0.4 0.6,但应该与 A B 组合相反,因此是 -0.1 -0.3 0.9
猜你喜欢
  • 2013-06-03
  • 1970-01-01
  • 2012-02-21
  • 2022-07-28
  • 2014-05-03
  • 2011-10-31
  • 2020-10-23
  • 1970-01-01
  • 2021-08-25
相关资源
最近更新 更多