【问题标题】:Reshaping\Stacking Multiple Variables in R, Triads to Dyads重塑\堆叠R中的多个变量,三元组到二元组
【发布时间】:2013-01-06 04:43:02
【问题描述】:

我有数据描述了一个人(玩家 1)与其他两个人(玩家 2 和玩家 3)的互动。每一行都描述了玩家的独特组合,但我想分别分析玩家 1 到玩家 2 和玩家 1 到玩家 3 对子。为了实现这一点,我设想了某种堆叠,我可以在其中融合玩家二和三的描述性变量,同时在每一行中保留玩家 1 的数据。让事情变得更复杂,我对每个人都有多个描述性变量。

这里有一小部分数据可供使用(实际上,我想要堆叠/融化的玩家 2 和 3 的描述性变量要多得多):

    p1_id <- c(1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1032, 1032, 1032, 1032, 1032, 1032)
    p1_age <- c(53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 45, 45, 45, 45, 45)
    p2_id <- c(14372, 15022,  9072, 15052, 2161, 18381, 15032, 14451, 16322, 11142, 8182,  1131, 7092, 4071, 16191, 18142, 4222, 11052, 2202, 16151)
    p2_money <- c(4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 0, 0, 10, 0, 6, 6, 4, 6, 6)
    p2_age <- c(50, 33, 56, 23, 29, 26, 28, 34, 20, 41, 34, 45, 23, 35, 25, 30, 40, 41, 45, 28)
    p3_id <- c(5151, 16181, 5182, 18462, 7231, 14372, 3052, 14532, 4152, 15012, 19212, 9062, 9032, 18351, 14461, 16291, 17102, 10102, 7051, 16282)
    p3_money <- c(4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 10, 10, 0, 10, 6, 6, 4, 6, 4)
    p3_age <- c(30, 29, 22, 22, 43, 50, 23, 32, 31, 46, 36, 36, 21, 27, 49, 38, 40, 48, 26, 32)
    df <- data.frame(p1_id, p1_age, p2_id, p2_money, p2_age, p3_id, p3_money, p3_age)

数据框:

     p1_id p1_age p2_id p2_money p2_age p3_id p3_money p3_age
     1   1021     53 14372        4     50  5151        4     30
     2   1021     53 15022        2     33 16181        2     29
     3   1021     53  9072        2     56  5182        2     22
     4   1021     53 15052        2     23 18462        2     22
     5   1021     53  2161        2     29  7231        2     43
     6   1021     53 18381        2     26 14372        2     50
     7   1021     53 15032        2     28  3052        2     23
     8   1021     53 14451        2     34 14532        2     32
     9   1021     53 16322        2     20  4152        2     31
     10  1021     53 11142        2     41 15012        2     46
     11  1021     53  8182       10     34 19212        0     36
     12  1021     53  1131        0     45  9062       10     36
     13  1021     53  7092        0     23  9032       10     21
     14  1021     53  4071       10     35 18351        0     27
     15  1032     53 16191        0     25 14461       10     49
     16  1032     45 18142        6     30 16291        6     38
     17  1032     45  4222        6     40 17102        6     40
     18  1032     45 11052        4     41 10102        4     48
     19  1032     45  2202        6     45  7051        6     26
     20  1032     45 16151        6     28 16282        4     32

如果我上面的描述过于混乱,以下是我希望重整后的数据的外观:

     row p1_id p1_age p23_id p23_money p23_age 
     1   1021     53 14372        4     50  
     2   1021     53 15022        2     33 
     3   1021     53  9072        2     56  
     4   1021     53 15052        2     23 
     5   1021     53  2161        2     29  
     6   1021     53 18381        2     26 
     7   1021     53 15032        2     28 
     8   1021     53 14451        2     34
     9   1021     53 16322        2     20
     10  1021     53 11142        2     41 
     11  1021     53  8182       10     34 
     12  1021     53  1131        0     45  
     13  1021     53  7092        0     23  
     14  1021     53  4071       10     35 
     15  1032     53 16191        0     25 
     16  1032     45 18142        6     30 
     17  1032     45  4222        6     40 
     18  1032     45 11052        4     41 
     19  1032     45  2202        6     45  
     20  1032     45 16151        6     28 
     21  1021     53  5151        4     30  
     22  1021     53 16181        2     29
     23  1021     53  5182        2     22
     24  1021     53 18462        2     22
     25  1021     53  7231        2     43 
     26  1021     53 14372        2     50
     27  1021     53  3052        2     23 
     28  1021     53 14532        2     32 
     28  1021     53  4152        2     31
     30  1021     53 19212        0     36
     31  1021     53  9062       10     36 
     32  1021     53  9032       10     21 
     33  1021     53 18351        0     27
     34  1032     53 16191        0     25
     35  1032     53 14461       10     49
     36  1032     53 16291        6     38
     37  1032     53 17102        6     40 
     38  1032     53 10102        4     48 
     39  1032     53  7051        6     26 
     40  1032     53 16282        4     32

感谢您的帮助!

【问题讨论】:

  • 你想做什么?您尝试实现哪种类型的比较,我认为将所有行放在一起不会有助于进一步分析。 aP1没有money变量也是正常的吗?
  • 这些答案对您有什么影响?如果您对其中任何一个感到满意,请务必给他们投票;如果其中一个解决了您的问题或帮助您解决问题,请考虑通过单击答案旁边的大复选标记将其标记为已接受。
  • 谢谢!我实际上正在尝试它们。我一定会投上一票。

标签: r reshape


【解决方案1】:

如果您按如下方式修改列名,这很容易做到:

names(df) <- gsub("(.*)_(.*)", "\\2\\.\\1", names(df))
names(df)
# [1] "id.p1"    "age.p1"   "id.p2"    "money.p2" 
# [5] "age.p2"   "id.p3"    "money.p3" "age.p3"

接下来,使用 data.frame 的“row.names”作为基础 R reshape() 中的“idvar”。

reshape(df, direction = "long", idvar = "row.names",
        timevar = "person", varying = 3:8)
#       id.p1 age.p1 person    id money age row.names
# 1.p2   1021     53     p2 14372     4  50         1
# 2.p2   1021     53     p2 15022     2  33         2
# 3.p2   1021     53     p2  9072     2  56         3
# 4.p2   1021     53     p2 15052     2  23         4
# 5.p2   1021     53     p2  2161     2  29         5
# 6.p2   1021     53     p2 18381     2  26         6
# 7.p2   1021     53     p2 15032     2  28         7
# 8.p2   1021     53     p2 14451     2  34         8
# 9.p2   1021     53     p2 16322     2  20         9
# 10.p2  1021     53     p2 11142     2  41        10
# 11.p2  1021     53     p2  8182    10  34        11
# 12.p2  1021     53     p2  1131     0  45        12
# 13.p2  1021     53     p2  7092     0  23        13
# 14.p2  1021     53     p2  4071    10  35        14
# 15.p2  1032     53     p2 16191     0  25        15
# 16.p2  1032     45     p2 18142     6  30        16
# 17.p2  1032     45     p2  4222     6  40        17
# 18.p2  1032     45     p2 11052     4  41        18
# 19.p2  1032     45     p2  2202     6  45        19
# 20.p2  1032     45     p2 16151     6  28        20
# 1.p3   1021     53     p3  5151     4  30         1
# 2.p3   1021     53     p3 16181     2  29         2
# 3.p3   1021     53     p3  5182     2  22         3
# 4.p3   1021     53     p3 18462     2  22         4
# 5.p3   1021     53     p3  7231     2  43         5
# 6.p3   1021     53     p3 14372     2  50         6
# 7.p3   1021     53     p3  3052     2  23         7
# 8.p3   1021     53     p3 14532     2  32         8
# 9.p3   1021     53     p3  4152     2  31         9
# 10.p3  1021     53     p3 15012     2  46        10
# 11.p3  1021     53     p3 19212     0  36        11
# 12.p3  1021     53     p3  9062    10  36        12
# 13.p3  1021     53     p3  9032    10  21        13
# 14.p3  1021     53     p3 18351     0  27        14
# 15.p3  1032     53     p3 14461    10  49        15
# 16.p3  1032     45     p3 16291     6  38        16
# 17.p3  1032     45     p3 17102     6  40        17
# 18.p3  1032     45     p3 10102     4  48        18
# 19.p3  1032     45     p3  7051     6  26        19
# 20.p3  1032     45     p3 16282     4  32        20

更新:使用“reshape2”中的dcast()

希望更精通“reshape2”包(或可能使用“plyr”)的人能够提出比以下更简洁的解决方案。该解决方案涉及:

  1. 一个虚拟的“id”列。
  2. “融化”数据集。
  3. 使用colsplit()(来自“reshape2”)生成几个新列。
  4. 使用dcast() 获得所需的表单。

它是这样的:

df$id <- 1:nrow(df)
df2 <- melt(df, id.vars=c("id", "p1_id", "p1_age"))
df2 <- cbind(df2[-4], 
             colsplit(df2$variable, "_", c("person", "var")))
head(df2)
out <- dcast(df2, id + p1_id + p1_age + person ~ var)
list(head(out), tail(out))
# [[1]]
#   id p1_id p1_age person age    id money
# 1  1  1021     53     p2  50 14372     4
# 2  1  1021     53     p3  30  5151     4
# 3  2  1021     53     p2  33 15022     2
# 4  2  1021     53     p3  29 16181     2
# 5  3  1021     53     p2  56  9072     2
# 6  3  1021     53     p3  22  5182     2
# 
# [[2]]
#    id p1_id p1_age person age    id money
# 35 18  1032     45     p2  41 11052     4
# 36 18  1032     45     p3  48 10102     4
# 37 19  1032     45     p2  45  2202     6
# 38 19  1032     45     p3  26  7051     6
# 39 20  1032     45     p2  28 16151     6
# 40 20  1032     45     p3  32 16282     4

因此,基本上,无论您采用何种方法,您似乎都必须对您的 data.frame 进行一些预处理,以使其格式更适合此类转换。

【讨论】:

  • 抱歉编辑。没有注意我复制和粘贴的尝试。我想这些编辑的寓意是“不要在做午餐时回答关于 SO 的问题。”
  • 我可以建议使用 sep='_' 来避免重命名步骤吗?
  • @agstudy,您可能会这样做,但由于reshape() 的工作方式,您仍然需要进行一些操作。请注意,在重命名步骤中,我正在颠倒什么被认为是“时间”和什么被认为是“变量”。如果您使用sep = "_" 提出了一个很酷的解决方案,请分享!
  • 哎呀..好抓!我现在才看到! +1(聪明的反转)..我想我需要一杯咖啡重新阅读重塑帮助!
  • @agstudy,相信我,即使是四杯咖啡也无济于事。我认为reshape() 帮助页面可以从更多示例中受益,这些示例展示了不同的参数如何影响输出。
【解决方案2】:

这可能不是最有效的方法,但我认为它可以满足您的需求。

df <- data.frame(p1_id, p1_age, p2_id, p2_money, p2_age, p3_id, p3_money, p3_age)

player2 <- df[,names(df) %in% c('p1_id','p1_age','p2_id','p2_money','p2_age')]
colnames(player2) <- c('p1_id', 'p1_age', 'p23_id', 'p23_money', 'p23_age')

player3 <- df[,names(df) %in% c('p1_id','p1_age','p3_id','p3_money','p3_age')]
colnames(player3) <- c('p1_id', 'p1_age', 'p23_id', 'p23_money', 'p23_age')

df2 <- rbind(player2, player3)
df2

除了为什么您发布的数据集中 1032 的年龄会发生变化?玩家 1032 在一个数据集中是 45 岁,在另一个数据集中是 53 岁。所以我不明白一些事情,也许我的答案没有做你想做的事。

实际上,玩家 1032 在原始数据集的一行中是 53 岁,在五行中是 45 岁。一共6行。

在您的重构数据集中,玩家 1032 的年龄为 53 岁(分 8 行)和 45 岁(分 5 行)。一共13行。

这是印刷错误吗?如果不是,我的回答是错误的。

编辑:

假设我上面的回答是正确的并且假设列总是按玩家和属性排序,下面的代码将适用于任意数量的玩家属性,并且只需要更改n.player1df2 的列名。

df <- data.frame(p1_id, p1_age, p2_id, p2_money, p2_age, p3_id, p3_money, p3_age)

n.player1 <- 2

player2 <- df[,1:(n.player1+((ncol(df)-n.player1)/2))]
colnames(player2) <- paste("X", seq_along(1:ncol(player2)), sep="")

player3 <- df[,c(1:n.player1,(ncol(player2)+1):ncol(df))]
colnames(player3) <- paste("X", seq_along(1:ncol(player3)), sep="")

df2 <- rbind(player2, player3)
colnames(df2) <- c('p1_id', 'p1_age', 'p23_id', 'p23_money', 'p23_age')
df2

【讨论】:

    猜你喜欢
    • 2013-08-30
    • 2011-09-17
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    • 2017-05-05
    • 2011-07-11
    相关资源
    最近更新 更多