【问题标题】:Stacking multiple columns in R在R中堆叠多列
【发布时间】:2020-06-25 23:23:35
【问题描述】:

我正在尝试将数据帧转换为 R 中的长格式。 这是 9 天内在“id”网格中进行的调查的示例数据,如果感兴趣的变量被检测到“1”或未检测到“0”。 我想转换此数据框,以便将调查数量从 9 减少到 3 但现在每个调查期都包含 3 次访问。 我试图通过一次堆叠三列来做到这一点,以便通过添加一个名为“visit_no”的列来将调查访问“v1”到“v9”(在下图中)转换为 v1、v2、v3,该列描述调查期内的访问次数。
以下链接是当前形式的数据帧图像,下面是生成数据的代码

生成数据的代码:

id<- c(240,220,160)
v1<- c(rep(0,9))
v2<-c(rep(0,3),1,rep(0,5))
v3<- c(1,rep(0,8))

v<-as.data.frame(rbind(v1,v2,v3))

survey<- cbind(id,v)
survey

这是我需要的数据框图片的链接

参考数据框

【问题讨论】:

  • 您生成调查数据的代码与发布的图片不匹配。

标签: r tidyverse reshape tidyr


【解决方案1】:

一种方法是在 base R"

中使用 reshape
reshape(survey, direction="long", idvar="id",
        varying=list(c("V1","V4","V7"), c("V2","V5","V8"), c("V3","V6","V9")),
        v.names=c("Visit1", "Visit2", "Visit3"), timevar="visit_no") 

       id visit_no Visit1 Visit2 Visit3
240.1 240        1      0      0      0
220.1 220        1      0      0      0
160.1 160        1      1      0      0
240.2 240        2      0      0      0
220.2 220        2      1      0      0
160.2 160        2      0      0      0
240.3 240        3      0      0      0
220.3 220        3      0      0      0
160.3 160        3      0      0      0

如果你希望它按 id 排序,然后从 dplyr 添加arrange

 %>% dplyr::arrange(id)

   id visit_no Visit1 Visit2 Visit3
1 160        1      1      0      0
2 160        2      0      0      0
3 160        3      0      0      0
4 220        1      0      0      0
5 220        2      1      0      0
6 220        3      0      0      0
7 240        1      0      0      0
8 240        2      0      0      0
9 240        3      0      0      0

如果您的原始变量名称格式一致,那么 reshape 命令会更简单,因为它会正确地从名称中猜出时间。例如,

names(survey)[2:10] <- paste0(names(survey)[2:10], ".", rep(1:3, 3))
head(survey)
        id V1.1 V2.2 V3.3 V4.1 V5.2 V6.3 V7.1 V8.2 V9.3
v1 240    0    0    0    0    0    0    0    0    0
v2 220    0    0    0    1    0    0    0    0    0
v3 160    1    0    0    0    0    0    0    0    0

reshape(survey, direction="long", idvar="id",
        varying=2:10, # Can just give the indices now.
        v.names=c("Visit1", "Visit2", "Visit3"), timevar="visit_no") %>%
  arrange(id)

虽然时间格式一致,但原来的变量名不是,所以R无法猜测长格式的名称(Visit1,Visit2,Visit3),需要提供这些在v.names 参数中。

如果它们格式一致,那么重塑就更简单了。

names(survey)[2:10] <- paste0("Visit", rep(1:3, each=3), ".", rep(1:3, 3))
head(survey)    
    id Visit1.1 Visit1.2 Visit1.3 Visit2.1 Visit2.2 Visit2.3 Visit3.1 Visit3.2 Visit3.3
v1 240        0        0        0        0        0        0        0        0        0
v2 220        0        0        0        1        0        0        0        0        0
v3 160        1        0        0        0        0        0        0        0        0

reshape(survey, direction="long", varying=2:10, timevar="visit_no") %>%
  arrange(id)

tidyr 版本可能涉及两次重塑;一种是把所有东西都做成很长的形式,然后再把它恢复成更宽的形式(我称之为 1 step back, 2 steps forward 方法)。

【讨论】:

  • 谢谢!我的示例是数据的简化版本,该解决方案运行良好。
【解决方案2】:

您可以根据需要的顺序更改列的名称。

names(survey)[-1] <- paste(rep(paste0("visit", 1:3), each =3), 1:3, sep = "_")

names(survey)
#[1] "id"  "visit1_1" "visit1_2" "visit1_3" "visit2_1" "visit2_2" "visit2_3" 
#    "visit3_1" "visit3_2" "visit3_3"

然后使用pivot_longer from tidyr 获取不同列的数据。

tidyr::pivot_longer(survey, cols = -id, names_to = c(".value", "visit_no"),
                    names_sep = "_") %>%
       type.convert(as.is = TRUE)


# A tibble: 9 x 5
#     id visit_no visit1 visit2 visit3
#  <int>    <int>  <int>  <int>  <int>
#1   240        1      0      0      0
#2   240        2      0      0      0
#3   240        3      0      0      0
#4   220        1      0      1      0
#5   220        2      0      0      0
#6   220        3      0      0      0
#7   160        1      1      0      0
#8   160        2      0      0      0
#9   160        3      0      0      0

【讨论】:

    猜你喜欢
    • 2020-02-06
    • 1970-01-01
    • 2021-03-20
    • 2017-04-29
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多