【问题标题】:r "slot" two columns into one (like a zip)r “插槽”将两列合二为一(如 zip)
【发布时间】:2013-04-23 12:40:46
【问题描述】:

给定两列(可能来自数据帧)等长 N,我如何生成长度为 2N 的列,其中包含来自第一列的奇数项和第二列的偶数项?

假设我有以下数据框

df.1 <- data.frame(X = LETTERS[1:10], Y = 2*(1:10)-1, Z = 2*(1:10))

如何生成这个数据框df.2

i <- 1
j <- 0
XX <- NA
while (i <= 10){
XX[i+j] <- LETTERS[i]
XX[i+j+1]<- LETTERS[i]
i <- i+1
j <- i-1
}

df.2 <- data.frame(X.X = XX, Y.Z = c(1:20))

【问题讨论】:

  • Here's another way你可能有兴趣。
  • 您可以通过将它们放在列表中并执行以下操作将其扩展到多个向量:unlist(ll)[order(sequence(vapply(ll, length, 0L)))]

标签: r merge


【解决方案1】:

ggplot2 有一个未导出的函数 interleave 来执行此操作。

虽然未导出它确实有一个帮助页面 (?ggplot2:::interleave)

with(df.1, ggplot2:::interleave(Y,Z))
## [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20

【讨论】:

  • 有趣。我写了自己的交错,没有意识到已经有一个广泛使用的包中。
  • 这是一个很棒的解决方案。也可以轻松扩展到多个向量!
【解决方案2】:

如果我理解正确,您想在数据框中创建一个长度为向量 X、Y 和 Z 两倍的新向量,然后希望 X 的所有元素占据这个新向量的奇数索引,并且所有Y 的元素是偶数索引。如果是这样,那么下面的代码应该可以解决问题:

foo<-vector(length=2*nrow(df.1), mode='character')

foo[seq(from = 1, to = 2*length(df.1$X), by=2)]<-as.character(df.1$X)
foo[seq(from = 2, to = 2*length(df.1$X), by=2)]<-df.1$Y

注意,我先创建一个长度为 20 的空向量 foo,然后用 df.1$X 和 df.1$Y 的元素填充它。

干杯,

丹尼

【讨论】:

  • 这是 ggplot2:::interleave() 解决方案的第二次。你的似乎更安全,但只是更长一点!
【解决方案3】:

您可以从reshape2 使用melt

library(reshape2)
foo <- melt(df.1, id.vars='X')

> foo
   X variable value
1  A        Y     1
2  B        Y     3
3  C        Y     5
4  D        Y     7
5  E        Y     9
6  F        Y    11
7  G        Y    13
8  H        Y    15
9  I        Y    17
10 J        Y    19
11 A        Z     2
12 B        Z     4
13 C        Z     6
14 D        Z     8
15 E        Z    10
16 F        Z    12
17 G        Z    14
18 H        Z    16
19 I        Z    18
20 J        Z    20

然后你可以排序并选择你想要的列:

foo[order(foo$X), c('X', 'value')]

【讨论】:

  • 对我的示例来说很好的解决方案,但可能是订购 X 会给出错误的结果。
【解决方案4】:

使用基础 R 的另一种解决方案。

首先使用向量[1,1,2,2 ... 10,10] 索引data.frame 的字符向量并存储为X.X。接下来,rbind data.frame 向量 YZ 有效地“压缩”它们并存储在 Y.X 中。

> res <- data.frame(
+   X.X = df.1$X[c(rbind(1:10, 1:10))],
+   Y.Z = c(rbind(df.1$Y, df.1$Z))
+ )
> head(res)
  X.X Y.Z
1   A   1
2   A   2
3   B   3
4   B   4
5   C   5
6   C   6

【讨论】:

  • 您也可以将X.X 行替换为rep(df.1$X,each=2)
  • 谢谢!我自己是 R 新手,发现最好的学习方法是在 SO 上回答初学者 Qs。很棒的提示!
【解决方案5】:

一个 one 基础 R 中的两个衬垫:

test <- data.frame(X.X=df.1$X,Y.Z=unlist(df.1[c("Y","Z")]))
test[order(test$X.X),]

【讨论】:

    【解决方案6】:

    假设您想要您在第一段中要求的内容,而您发布的其余内容是您解决它的尝试。

    a=df.1[df.1$Y%%2>0,1:2]
    b=df.1[df.1$Z%%2==0,c(1,3)]
    names(a)=c("X.X","Y.Z")
    names(b)=names(a)
    df.2=rbind(a, b)
    

    如果您想按照示例中的 X.X 对它们进行分组,您可以这样做:

    library(plyr)
    arrange(df.2, X.X)
    

    【讨论】:

    • 是的,抱歉,我的示例具有误导性。它旨在成为一般问题和相应解决方案的特定实例。用于说明目的。
    • 知道了。从您选择的响应来看,您也只是在寻找奇数与偶数索引的拆分。我将您的问题解释为寻找奇数与偶数值的分割......
    猜你喜欢
    • 2022-10-23
    • 2015-12-30
    • 1970-01-01
    • 1970-01-01
    • 2016-11-28
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    相关资源
    最近更新 更多