拆分R中的多个列

时间:2014-07-13 18:26:43

标签: r dataframe

我有以下数据框:

olddf <- structure(list(test = structure(1:6, .Label = c("test1", "test2", 
"test3", "test4", "test5", "test6"), class = "factor"), month0_gp1 = c("163±28", 
"133±20", "177±29", "153±30", "161±31", "159±23"), month0_gp2 = c("122±17", 
"167±20", "146±26", "150±27", "148±33", "161±37"), month1_gp1 = c("157±32", 
"152±37", "151±24", "143±25", "144±29", "126±30"), month1_gp2 = c("181±14", 
"133±34", "152±38", "144±30", "148±20", "137±19"), month3_gp1 = c("139±38", 
"161±39", "166±38", "162±39", "151±38", "155±38"), month3_gp2 = c("151±40", 
"161±33", "137±25", "161±31", "168±30", "147±34")), .Names = c("test", 
"month0_gp1", "month0_gp2", "month1_gp1", "month1_gp2", "month3_gp1", 
"month3_gp2"), row.names = c(NA, 6L), class = "data.frame")

   test month0_gp1 month0_gp2 month1_gp1 month1_gp2 month3_gp1 month3_gp2
1 test1     163±28     122±17     157±32     181±14     139±38     151±40
2 test2     133±20     167±20     152±37     133±34     161±39     161±33
3 test3     177±29     146±26     151±24     152±38     166±38     137±25
4 test4     153±30     150±27     143±25     144±30     162±39     161±31
5 test5     161±31     148±33     144±29     148±20     151±38     168±30
6 test6     159±23     161±37     126±30     137±19     155±38     147±34

我必须将列2:7分成2个(一个用于平均值,另一个用于sd):

test month0_gp1_mean month0_gp1_sd month0_gp2_mean month0_gp2_sd month1_gp1_mean month1_gp1_sd  ....

我查看了之前的帖子并使用了do.call(rbind...方法:

mydf <- data.frame(do.call(rbind, strsplit(olddf$month0_gp1,'±')))

mydf
   X1 X2
1 163 28
2 133 20
3 177 29
4 153 30
5 161 31
6 159 23

但这一次适用于一列。如何修改它以循环2:7列,并将它们组合成一个新的数据帧?谢谢你的帮助。

2 个答案:

答案 0 :(得分:6)

首先,获取my cSplit function from this GitHub Gist

其次,将其分开:

cSplit(olddf, 2:ncol(olddf), sep = "±")
#     test 2_1 2_2 3_1 3_2 4_1 4_2 5_1 5_2 6_1 6_2 7_1 7_2
# 1: test1 163  28 122  17 157  32 181  14 139  38 151  40
# 2: test2 133  20 167  20 152  37 133  34 161  39 161  33
# 3: test3 177  29 146  26 151  24 152  38 166  38 137  25
# 4: test4 153  30 150  27 143  25 144  30 162  39 161  31
# 5: test5 161  31 148  33 144  29 148  20 151  38 168  30
# 6: test6 159  23 161  37 126  30 137  19 155  38 147  34

如果要在同一步骤中进行列重命名,请尝试:

Nam <- names(olddf)[2:ncol(olddf)]
setnames(
  cSplit(olddf, 2:ncol(olddf), sep = "±"), 
  c("test", paste(rep(Nam, each = 2), c("mean", "sd"), sep = "_")))[]

另一种选择是查看dplyr + tidyr

这是我能想到的最好的,但我不确定这是否是使用这些工具做到这一点的正确方法....

olddf %>%
  gather(GM, value, -test) %>%          # Makes the data somewhat long
  separate(value, c("MEAN", "SD")) %>%  # Splits "value" column. We're wide again
  gather(MSD, value, -test, -GM) %>%    # Makes the data long again
  unite(var, GM, MSD) %>%               # Combines GM and MSD columns
  spread(var, value)                    # Goes from wide to long

这相当于melt数据一次,在结果“值”列上使用colsplit,再次melt数据,并使用{{1}获得宽格式。

答案 1 :(得分:2)

这是一个qdap方法:

library(qdap)
for(i in seq(2, 13, by = 2)){
    olddf <- colsplit2df(olddf, i, 
        paste0(names(olddf)[i], "_", c("mean", "sd")), sep = "±")
}

olddf[,-1] <- lapply(olddf[,-1], as.numeric)
olddf

我首先看了Ananda的splitstackshape包,因为我觉得有一个简单的方法可以做到这一点,但我找不到办法。

不确定您是否需要将列转换为数字的最后一行,但假设您愿意。