将两个变量的数据从宽数据转换为长数据
Converting data from wide to long for two variables
我有一个包含两个宽格式变量的数据集,我想将其转换为长格式。我看过 R 厨师的例子,但它们只针对一个变量。
我的数据集 (graph.dat) 如下所示:
PH25 PH50 PH75 PH100 P25 P50 P75 P100 r_b c
3.96 5.94 5.94 5.94 1,694 1,736 1,329 800 0.029 7
2.86 2.86 2.86 2.86 1,665 1,792 1,639 1,335 0.027 7
3.96 5.72 5.72 5.72 1,580 1,560 1,156 663 0.023 7
我想绘制 PH(x 轴)与 P(y 轴)的关系图。所以对于一个PH25值对应一个P25的值(和一个r_b和c的值);所以长格式将是:
PH P r_b c
3.96 1,694 0.029 7
2.86 1,665 0.027 7
3.96 1,580 0.023 7
5.94 1,736 0.029 7
2.86 1,792 0.027 7
5.72 1,560 0.023 7
5.94 1,329 0.029 7
2.86 1,639 0.027 7
5.72 1,156 0.023 7
5.94 800 0.029 7
2.86 1,335 0.027 7
5.72 663 0.023 7
我尝试 "melt" 两次,但没有用。
这是我所做的:
graph.dat1<- melt(graph.dat, id.vars=c("PH25","PH50","PH75",
"PH100","r_b", "c"),
variable.name="P",
value.name="Pval")
和新数据集 (graph.dat1) 很好,因为每个 "P" 我只有三个值(总共给我 12 个观察值)。它看起来像这样:
PH25 PH50 PH75 PH100 r_b c P Pval
1 3.96 5.94 5.94 5.94 0.029 7 P25 1694
2 2.86 2.86 2.86 2.86 0.027 7 P25 1665
3 3.96 5.72 5.72 5.72 0.023 7 P25 1580
4 3.96 5.94 5.94 5.94 0.029 7 P50 1736
5 2.86 2.86 2.86 2.86 0.027 7 P50 1792
6 3.96 5.72 5.72 5.72 0.023 7 P50 1560
7 3.96 5.94 5.94 5.94 0.029 7 P75 1329
8 2.86 2.86 2.86 2.86 0.027 7 P75 1639
9 3.96 5.72 5.72 5.72 0.023 7 P75 1156
10 3.96 5.94 5.94 5.94 0.029 7 P100 800
11 2.86 2.86 2.86 2.86 0.027 7 P100 1335
12 3.96 5.72 5.72 5.72 0.023 7 P100 663
但是当我执行第二个 "melt" 时它不起作用,我不知道如何解决它。这是我做的第二步:
graph.dat2<- melt (graph.dat1,id.vars=c("r_b", "c", "P", "Pval"),
variable.name="PdH",
value.name="PH")
但是我得到了 4 倍的观察结果(所以我得到了 48 个观察结果而不是 12 个观察结果)。所以,我的新数据集 (graph.dat2) 看起来像:
r_b c P Pval PdH PH
1 0.029 7 P25 1694 PH25 3.96
2 0.027 7 P25 1665 PH25 2.86
3 0.023 7 P25 1580 PH25 3.96
4 0.029 7 P50 1736 PH25 3.96
5 0.027 7 P50 1792 PH25 2.86
6 0.023 7 P50 1560 PH25 3.96
7 0.029 7 P75 1329 PH25 3.96
8 0.027 7 P75 1639 PH25 2.86
9 0.023 7 P75 1156 PH25 3.96
10 0.029 7 P100 800 PH25 3.96
11 0.027 7 P100 1335 PH25 2.86
12 0.023 7 P100 663 PH25 3.96
13 0.029 7 P25 1694 PH50 5.94
14 0.027 7 P25 1665 PH50 2.86
15 0.023 7 P25 1580 PH50 5.72
...
data.table
的最新版本允许 melt
multiple columns simultaneously。
不幸的是,两组列都以字母 P
开头。简单地指定 patterns("PH", "P")
将不起作用,因为 P
将匹配 PH
列以及 P
列,导致 24 行而不是 12 行。稍微修改的正则表达式 patterns("PH", "P\d")
将工作:
library(data.table) # CRAN version 1.10.4 used
graph.dat1 <- melt(setDT(graph.dat), measure.vars = patterns("PH", "P\d"),
value.name = c("PH", "P"))
# rename factor levels of variable
graph.dat1[, variable := forcats::lvls_revalue(variable, c("25", "50", "75", "100"))][]
r_b c variable PH P
1: 0.029 7 25 3.96 1,694
2: 0.027 7 25 2.86 1,665
3: 0.023 7 25 3.96 1,580
4: 0.029 7 50 5.94 1,736
5: 0.027 7 50 2.86 1,792
6: 0.023 7 50 5.72 1,560
7: 0.029 7 75 5.94 1,329
8: 0.027 7 75 2.86 1,639
9: 0.023 7 75 5.72 1,156
10: 0.029 7 100 5.94 800
11: 0.027 7 100 2.86 1,335
12: 0.023 7 100 5.72 663
请注意,需要使用 setDT(graph.dat)
或 data.table(graph.dat)
将 graph.dat
强制转换为 data.table
对象。否则,reshape2::melt()
将被调度到无法识别 patterns()
.
的 data.frame 对象上
另请注意,类似问题有一个答案 here,但要求的 patterns()
完全不同。
数据
library(data.table)
graph.dat <- fread(
"PH25 PH50 PH75 PH100 P25 P50 P75 P100 r_b c
3.96 5.94 5.94 5.94 1,694 1,736 1,329 800 0.029 7
2.86 2.86 2.86 2.86 1,665 1,792 1,639 1,335 0.027 7
3.96 5.72 5.72 5.72 1,580 1,560 1,156 663 0.023 7",
data.table = FALSE)
基于 R 的替代解决方案是:
df <- read.table(header=TRUE, text="PH25 PH50 PH75 PH100 P25 P50 P75 P100 r_b c
3.96 5.94 5.94 5.94 1,694 1,736 1,329 800 0.029 7
2.86 2.86 2.86 2.86 1,665 1,792 1,639 1,335 0.027 7
3.96 5.72 5.72 5.72 1,580 1,560 1,156 663 0.023 7")
(want<-do.call(rbind,
Map(
function(x,y) data.frame(PH=df[[x]],P=df[[y]],r_b=df$r_b,c=df$c),
c("PH25","PH50","PH75","PH100"),
c("P25","P50","P75","P100")
)))
基本 R 也不太难 reshape
:
reshape(df, direction="long", varying=list(paste0("PH", 1:4*25), paste0("P", 1:4*25)))
# note: paste0("PH", 1:4*25) is shortcut for c("PH25", "PH50", "PH75", "PH100")
.. 正确设置名称(PH
而不是长格式的 PH25
):
reshape(df, direction="long", varying=list(paste0("PH", 1:4*25), paste0("P", 1:4*25)),
v.names=c("PH", "P"))
我有一个包含两个宽格式变量的数据集,我想将其转换为长格式。我看过 R 厨师的例子,但它们只针对一个变量。
我的数据集 (graph.dat) 如下所示:
PH25 PH50 PH75 PH100 P25 P50 P75 P100 r_b c
3.96 5.94 5.94 5.94 1,694 1,736 1,329 800 0.029 7
2.86 2.86 2.86 2.86 1,665 1,792 1,639 1,335 0.027 7
3.96 5.72 5.72 5.72 1,580 1,560 1,156 663 0.023 7
我想绘制 PH(x 轴)与 P(y 轴)的关系图。所以对于一个PH25值对应一个P25的值(和一个r_b和c的值);所以长格式将是:
PH P r_b c
3.96 1,694 0.029 7
2.86 1,665 0.027 7
3.96 1,580 0.023 7
5.94 1,736 0.029 7
2.86 1,792 0.027 7
5.72 1,560 0.023 7
5.94 1,329 0.029 7
2.86 1,639 0.027 7
5.72 1,156 0.023 7
5.94 800 0.029 7
2.86 1,335 0.027 7
5.72 663 0.023 7
我尝试 "melt" 两次,但没有用。 这是我所做的:
graph.dat1<- melt(graph.dat, id.vars=c("PH25","PH50","PH75",
"PH100","r_b", "c"),
variable.name="P",
value.name="Pval")
和新数据集 (graph.dat1) 很好,因为每个 "P" 我只有三个值(总共给我 12 个观察值)。它看起来像这样:
PH25 PH50 PH75 PH100 r_b c P Pval
1 3.96 5.94 5.94 5.94 0.029 7 P25 1694
2 2.86 2.86 2.86 2.86 0.027 7 P25 1665
3 3.96 5.72 5.72 5.72 0.023 7 P25 1580
4 3.96 5.94 5.94 5.94 0.029 7 P50 1736
5 2.86 2.86 2.86 2.86 0.027 7 P50 1792
6 3.96 5.72 5.72 5.72 0.023 7 P50 1560
7 3.96 5.94 5.94 5.94 0.029 7 P75 1329
8 2.86 2.86 2.86 2.86 0.027 7 P75 1639
9 3.96 5.72 5.72 5.72 0.023 7 P75 1156
10 3.96 5.94 5.94 5.94 0.029 7 P100 800
11 2.86 2.86 2.86 2.86 0.027 7 P100 1335
12 3.96 5.72 5.72 5.72 0.023 7 P100 663
但是当我执行第二个 "melt" 时它不起作用,我不知道如何解决它。这是我做的第二步:
graph.dat2<- melt (graph.dat1,id.vars=c("r_b", "c", "P", "Pval"),
variable.name="PdH",
value.name="PH")
但是我得到了 4 倍的观察结果(所以我得到了 48 个观察结果而不是 12 个观察结果)。所以,我的新数据集 (graph.dat2) 看起来像:
r_b c P Pval PdH PH
1 0.029 7 P25 1694 PH25 3.96
2 0.027 7 P25 1665 PH25 2.86
3 0.023 7 P25 1580 PH25 3.96
4 0.029 7 P50 1736 PH25 3.96
5 0.027 7 P50 1792 PH25 2.86
6 0.023 7 P50 1560 PH25 3.96
7 0.029 7 P75 1329 PH25 3.96
8 0.027 7 P75 1639 PH25 2.86
9 0.023 7 P75 1156 PH25 3.96
10 0.029 7 P100 800 PH25 3.96
11 0.027 7 P100 1335 PH25 2.86
12 0.023 7 P100 663 PH25 3.96
13 0.029 7 P25 1694 PH50 5.94
14 0.027 7 P25 1665 PH50 2.86
15 0.023 7 P25 1580 PH50 5.72
...
data.table
的最新版本允许 melt
multiple columns simultaneously。
不幸的是,两组列都以字母 P
开头。简单地指定 patterns("PH", "P")
将不起作用,因为 P
将匹配 PH
列以及 P
列,导致 24 行而不是 12 行。稍微修改的正则表达式 patterns("PH", "P\d")
将工作:
library(data.table) # CRAN version 1.10.4 used
graph.dat1 <- melt(setDT(graph.dat), measure.vars = patterns("PH", "P\d"),
value.name = c("PH", "P"))
# rename factor levels of variable
graph.dat1[, variable := forcats::lvls_revalue(variable, c("25", "50", "75", "100"))][]
r_b c variable PH P 1: 0.029 7 25 3.96 1,694 2: 0.027 7 25 2.86 1,665 3: 0.023 7 25 3.96 1,580 4: 0.029 7 50 5.94 1,736 5: 0.027 7 50 2.86 1,792 6: 0.023 7 50 5.72 1,560 7: 0.029 7 75 5.94 1,329 8: 0.027 7 75 2.86 1,639 9: 0.023 7 75 5.72 1,156 10: 0.029 7 100 5.94 800 11: 0.027 7 100 2.86 1,335 12: 0.023 7 100 5.72 663
请注意,需要使用 setDT(graph.dat)
或 data.table(graph.dat)
将 graph.dat
强制转换为 data.table
对象。否则,reshape2::melt()
将被调度到无法识别 patterns()
.
另请注意,类似问题有一个答案 here,但要求的 patterns()
完全不同。
数据
library(data.table)
graph.dat <- fread(
"PH25 PH50 PH75 PH100 P25 P50 P75 P100 r_b c
3.96 5.94 5.94 5.94 1,694 1,736 1,329 800 0.029 7
2.86 2.86 2.86 2.86 1,665 1,792 1,639 1,335 0.027 7
3.96 5.72 5.72 5.72 1,580 1,560 1,156 663 0.023 7",
data.table = FALSE)
基于 R 的替代解决方案是:
df <- read.table(header=TRUE, text="PH25 PH50 PH75 PH100 P25 P50 P75 P100 r_b c
3.96 5.94 5.94 5.94 1,694 1,736 1,329 800 0.029 7
2.86 2.86 2.86 2.86 1,665 1,792 1,639 1,335 0.027 7
3.96 5.72 5.72 5.72 1,580 1,560 1,156 663 0.023 7")
(want<-do.call(rbind,
Map(
function(x,y) data.frame(PH=df[[x]],P=df[[y]],r_b=df$r_b,c=df$c),
c("PH25","PH50","PH75","PH100"),
c("P25","P50","P75","P100")
)))
基本 R 也不太难 reshape
:
reshape(df, direction="long", varying=list(paste0("PH", 1:4*25), paste0("P", 1:4*25)))
# note: paste0("PH", 1:4*25) is shortcut for c("PH25", "PH50", "PH75", "PH100")
.. 正确设置名称(PH
而不是长格式的 PH25
):
reshape(df, direction="long", varying=list(paste0("PH", 1:4*25), paste0("P", 1:4*25)),
v.names=c("PH", "P"))