R:从长到宽,顺序匹配对
R: long to wide with sequential matching pairs
我有如下所示的数据,其中 str 在 grp 中重复了 4 次。目的是将 out 变量转置为两列,与顺序匹配的 str 对相关联。例如,第 1 行的 str "dat" 应与第 3 行匹配。然后我们移动到与第 9 行匹配的第 2 行的 str "axy"。
现在我假设要开始,必须生成一个新因素,为每个 str 的第一个和第二个实例循环和编码,如果有一个简单的方法,我应该能够做到这一点检查字符串匹配,但是任何替代方法都会有所帮助。
Grp str out
1 dat 45
1 axy 76
1 dat 55
1 bte 61
1 cny 41
1 bte 34
1 cny 67
1 dat 32
1 axy 59
1 cny 12
1 dat 51
1 cny 50
1 bte 52
1 axy 38
1 bte 17
1 axy 78
2 ....
输出看起来像这样,每个 Grp 有 8 行。
Grp str1 out1 str2 out2
1 dat 45 dat 55
1 axy 76 axy 59
1 bte 61 bte 34
1 cny 41 cny 67
1 dat 32 dat 51
1 cny 12 cny 50
1 bte 52 bte 17
1 axy 38 axy 78
或者我猜是这样的,
Grp str1 out1 out2
1 dat 45 55
1 axy 76 59
1 bte 61 34
1 cny 41 67
1 dat 32 51
1 cny 12 50
1 bte 52 17
1 axy 38 78
split
和 lapply
适合这里:
foo <- lapply(split(df, df$str), function(x){
x$ind <- rep(1:2, nrow(x)/2);
x
})
foo <- do.call(rbind, foo)
foo <- split(foo[, -4], foo[,4])
foo <- data.frame(foo[[1]], foo[[2]])[, -c(4,5)]
names(foo)[c(3,4)] <- c("out1", "out2")
foo
Grp str out1 out2
axy.2 1 axy 76 59
axy.14 1 axy 38 78
bte.4 1 bte 61 34
bte.13 1 bte 52 17
cny.5 1 cny 41 67
cny.10 1 cny 12 50
dat.1 1 dat 45 55
dat.8 1 dat 32 51
如果您希望输出的行顺序与问题中显示的所需输出的行顺序相同,请尝试以下操作:
foo2 <- foo[order(as.numeric(gsub("\D", "", rownames(foo)))), ]
rownames(foo2) <- NULL
foo2
Grp str out1 out2
1 1 dat 45 55
2 1 axy 76 59
3 1 bte 61 34
4 1 cny 41 67
5 1 dat 32 51
6 1 cny 12 50
7 1 bte 52 17
8 1 axy 38 78
df
是你的 data.frame:
df <- read.table(text="Grp str out
1 dat 45
1 axy 76
1 dat 55
1 bte 61
1 cny 41
1 bte 34
1 cny 67
1 dat 32
1 axy 59
1 cny 12
1 dat 51
1 cny 50
1 bte 52
1 axy 38
1 bte 17
1 axy 78
", header=TRUE)
我有如下所示的数据,其中 str 在 grp 中重复了 4 次。目的是将 out 变量转置为两列,与顺序匹配的 str 对相关联。例如,第 1 行的 str "dat" 应与第 3 行匹配。然后我们移动到与第 9 行匹配的第 2 行的 str "axy"。
现在我假设要开始,必须生成一个新因素,为每个 str 的第一个和第二个实例循环和编码,如果有一个简单的方法,我应该能够做到这一点检查字符串匹配,但是任何替代方法都会有所帮助。
Grp str out
1 dat 45
1 axy 76
1 dat 55
1 bte 61
1 cny 41
1 bte 34
1 cny 67
1 dat 32
1 axy 59
1 cny 12
1 dat 51
1 cny 50
1 bte 52
1 axy 38
1 bte 17
1 axy 78
2 ....
输出看起来像这样,每个 Grp 有 8 行。
Grp str1 out1 str2 out2
1 dat 45 dat 55
1 axy 76 axy 59
1 bte 61 bte 34
1 cny 41 cny 67
1 dat 32 dat 51
1 cny 12 cny 50
1 bte 52 bte 17
1 axy 38 axy 78
或者我猜是这样的,
Grp str1 out1 out2
1 dat 45 55
1 axy 76 59
1 bte 61 34
1 cny 41 67
1 dat 32 51
1 cny 12 50
1 bte 52 17
1 axy 38 78
split
和 lapply
适合这里:
foo <- lapply(split(df, df$str), function(x){
x$ind <- rep(1:2, nrow(x)/2);
x
})
foo <- do.call(rbind, foo)
foo <- split(foo[, -4], foo[,4])
foo <- data.frame(foo[[1]], foo[[2]])[, -c(4,5)]
names(foo)[c(3,4)] <- c("out1", "out2")
foo
Grp str out1 out2
axy.2 1 axy 76 59
axy.14 1 axy 38 78
bte.4 1 bte 61 34
bte.13 1 bte 52 17
cny.5 1 cny 41 67
cny.10 1 cny 12 50
dat.1 1 dat 45 55
dat.8 1 dat 32 51
如果您希望输出的行顺序与问题中显示的所需输出的行顺序相同,请尝试以下操作:
foo2 <- foo[order(as.numeric(gsub("\D", "", rownames(foo)))), ]
rownames(foo2) <- NULL
foo2
Grp str out1 out2
1 1 dat 45 55
2 1 axy 76 59
3 1 bte 61 34
4 1 cny 41 67
5 1 dat 32 51
6 1 cny 12 50
7 1 bte 52 17
8 1 axy 38 78
df
是你的 data.frame:
df <- read.table(text="Grp str out
1 dat 45
1 axy 76
1 dat 55
1 bte 61
1 cny 41
1 bte 34
1 cny 67
1 dat 32
1 axy 59
1 cny 12
1 dat 51
1 cny 50
1 bte 52
1 axy 38
1 bte 17
1 axy 78
", header=TRUE)