【问题标题】:R reshape, restructure dataframe by chunksR重塑,按块重组数据帧
【发布时间】:2011-12-22 03:28:36
【问题描述】:

我正在尝试重塑数据框:

目前看起来是这样的:

ID   | Gender |A1 | A2 | A3 | B1 | B2 | B3
ID_1 | m      | 3 | 3  | 3  | 2  | 3  | 2 
ID_2 | f      | 1 | 1  | 1  | 4  | 4  | 4

我想要类似的东西:

 ID   | Gender | A1 | A2 | A3
 ID_1 | m      | 3  | 3  |  3   <- this would be columns A1 - A3 for ID 1
 ID_1 | m      | 2  | 2  |  2   <- this would be columns B1 - B3 for ID 1
 ID_2 | f      | 1  | 1  |  1   <- this would be columns A1 - A3 for ID 2
 ID_2 | f      | 4  | 4  |  4   <- this would be columns B1 - B3 for ID 2

(A1 和 B1 / A2 和 B2 是相同的变量(就内容而言),因此例如:A1 和 B1 将是测试 1 的结果的变量,而 A2 和 B2 都包含测试的结果2. 因此,为了评估它,我需要将 Test1 的所有结果放在一列中,将 Test 2 的所有结果放在另一列中。 我试图用“融化”来解决这个问题,但它只会一个一个地融化数据帧,而不是块。 (因为我需要保持前 2 列的原样,并且只重新排列最后 4 列,但作为三个块) 还有其他想法吗?谢谢!

【问题讨论】:

  • 告诉melt前两列是id变量,即id.vars=...
  • 第一部分有效,保留第一列没问题,但是我不知道如何告诉 R 它应该重新排列所有的 Test1´s (A1, B1) / Test2´ s (A2, B2) 等在一列中。所以我最终得到三列而不是六列(示例二)......
  • @Elisa,这看起来像是您几个小时前创建的问题的副本。如果是,请关闭另一个。
  • 是的,有些人努力为那个答案...(顺便说一句,这个要好得多,您只需几行代码就可以得到非常简单的答案)...你也可能想为您的问题中的列添加名称。
  • 感谢您的所有想法。我会尝试它们,如果它有效,我会向你报告。原始数据框有更多的列和非常混乱的列名。所以我可能必须在重塑数据之前重命名它们

标签: r dataframe reshape chunks data-management


【解决方案1】:

我更喜欢 Brian 的回答,但这里有一种使用基本包的方法。虽然在我看来相当丑陋。

您的数据框:

DF
        id    sex v1 v2 v3 v4 v5 v6
    1 ID_1   male A1 A2 A3 B1 B2 B3
    2 ID_2 female A1 A2 A3 B1 B2 B3

代码

DFa<-subset(DF, select=c(1:5))
DFb<-subset(DF, select=c(1:2, 6:8))
colnames(DFb)<-colnames(DFa)
DF<-as.data.frame(rbind(DFa,DFb))
rownames(DF)<-1:nrow(DF)
DF[order(DF$id),] 

【讨论】:

  • 约翰我不同意。我看到输出与 OP 的预期结果相同。只有 4 行而不是 6 行,所以我不明白您的批评。
  • 我的回复和其他人的唯一区别是我没有为 A 和 B 提供单独的列,因为它是回复中固有的(尽管如果 A1、A2、B1 ...实际上是数字)并且我重新排序了行以匹配所需的结果。这是拆分列和重新堆叠的简单案例。
  • 当我第一次复制并粘贴您的代码时,由于某种原因,它变成了 6 行。现在没有了。对不起。
【解决方案2】:

一个使用来自基础 R 的 reshape 的衬垫。

reshape(dat, varying = 3:8, idvar = 1:2, direction = 'long', drop=FALSE, 
   timevar = 'Test')

           ID Gender Test Test1 Test2 Test3
ID_1.m.A ID_1      m    A    A1    A2    A3
ID_2.f.A ID_2      f    A    A1    A2    A3
ID_1.m.B ID_1      m    B    B1    B2    B3
ID_2.f.B ID_2      f    B    B1    B2    B3

【讨论】:

  • +1 -- 很难击败这个解决方案。任何人都知道如何(在单行内)放弃那些丑陋的row.names
  • 您可以通过添加参数new.row.names = 1:4 来删除row.name。如果你不想硬编码 4,你可以很容易地根据数据弄清楚如何计算它。
  • 这个计算是我无法/无法弄清楚的。哦,好吧——即使是双班轮,这也很不错。
  • 我已经有一段时间没有使用 reshape 了,但我想知道这不只是用单列 y 变量来重塑它吗?我似乎根本无法让它真正起作用(无法猜测变化)。
  • Elisa,如果所有应该重新整形的列都以 Fach 开头,那么 grep 可以帮助您为 varying 参数获取正确的列:varying = grep ("^Fach", colnames (origdata))。而idvar 只是其他列(类似于1 : (min (grep ("^Fach", colnames (origdata)) - 1),您可以尝试timevar = "Fach" [我这里没有R 来测试表达式,但至少这应该给你一个提示在哪里寻找解决方案]
【解决方案3】:

怎么样:

> dat <- data.frame(id=c("id1","id2"),gender=c("m","f"),a.1=1:2,a.2=1:2,a.3=1:2,b.1=3:4,b.2=3:4,b.3=3:4)
> dat1 <- dat[,-(3:5)]
> dat2 <- dat[,-(6:8)]
> names(dat1)[3:5] <- c("v1","v2","v3")
> names(dat2)[3:5] <- c("v1","v2","v3")
> 
> dat1$test <- "b"
> dat2$test <- "a"
> result <- rbind(dat1,dat2)
> dat
   id gender a.1 a.2 a.3 b.1 b.2 b.3
1 id1      m   1   1   1   3   3   3
2 id2      f   2   2   2   4   4   4
> result
   id gender v1 v2 v3 test
1 id1      m  3  3  3    b
2 id2      f  4  4  4    b
3 id1      m  1  1  1    a
4 id2      f  2  2  2    a

【讨论】:

    【解决方案4】:

    正如@Andrie 所说,第一步是将数据与您的给定列(ID 和性别)融合在一起。正如您所说,您的问题是确定哪些列然后“一起”。这是一种方法,最初将该信息编码为列名,然后从那里提取出来。

    首先是一些虚拟数据

    dat <- data.frame(ID=c("ID_1", "ID_2"), Gender=c("m","f"), 
      Test1.A = "A1", Test2.A = "A2", Test3.A = "A3",
      Test1.B = "B1", Test2.B = "B2", Test3.B = "B3", stringsAsFactors=FALSE)
    

    请注意,我为列命名的名称系统地表明它属于哪个测试和哪个组。

    > dat
        ID Gender Test1.A Test2.A Test3.A Test1.B Test2.B Test3.B
    1 ID_1      m      A1      A2      A3      B1      B2      B3
    2 ID_2      f      A1      A2      A3      B1      B2      B3
    

    使用reshape2

    library("reshape2")
    

    融合数据,然后取出其中包含两条信息(测试和组)的variable 列,并将这两条信息分成两个单独的列。

    dat.m <- melt(dat, id.vars=c("ID", "Gender"))
    dat.m <- cbind(dat.m, colsplit(dat.m$variable, "\\.", names=c("Test", "Group")))
    

    现在很容易投射,因为测试和组是分开的。

    dcast(dat.m, ID+Gender+Group~Test)
    

    这给了

    > dcast(dat.m, ID+Gender+Group~Test)
        ID Gender Group Test1 Test2 Test3
    1 ID_1      m     A    A1    A2    A3
    2 ID_1      m     B    B1    B2    B3
    3 ID_2      f     A    A1    A2    A3
    4 ID_2      f     B    B1    B2    B3
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 2014-03-10
      • 2017-11-04
      • 1970-01-01
      相关资源
      最近更新 更多