微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

R中的数据透视/重塑

如何解决R中的数据透视/重塑

谢谢大家的回答,我以为自己比以前聪明,希望我能理解其中的任何一个。我想我也弄乱了我的数据可视化。我已经编辑了帖子,以更好地显示示例数据。很抱歉给您带来不便,我真的希望有人能帮助我。

我有一个关于重塑数据的问题。收集的数据如下:

 data <- read.table(header=T,text='
  pid     measurement1     Tdays1     measurement2      Tdays2     measurement3     Tdays3  measurment4    Tdays4 
   1         1356           1435         1483            1405         1563           1374       NA           NA     
   2         943            1848         1173            1818         1300           1785       NA           NA     
   3         1590           185          NA              NA           NA             NA         1585         294    
   4         130            72           443             70           NA             NA         136          79     
   4         140            82           NA              NA           NA             NA         756          89     
   4         220            126          266             124          NA             NA         703          128    
   4         166            159          213             156          476            145        776          166    
   4         380            189          583             173          NA             NA         586          203    
   4         353            231          510             222          656            217        526          240    
   4         180            268          NA              NA           NA             NA         NA           NA       
   4         NA             NA           NA              NA           NA             NA         580          278    
   4         571            334          596             303          816            289        483          371    
  ')

现在,我希望它看起来像这样:

PID     Time   Value
 1       1435   1356
 1       1405   1483
 1       1374   1563
 2       1848   943
 2       1818   1173
 2       1785   1300
 3       185    1590
...     ...     ... 

我将如何到达那里?我查了一些关于从宽到长格式的内容,但似乎并不能解决问题。是Rstudio和Stackoverflow的新功能(如果您还不能确定的话)。

致以问候,谢谢。

解决方法

这里的pivot_longer()版本略有不同。

library(tidyr)
library(dplyr)
dw %>% 
  pivot_longer(cols = -PID,names_to =".value",names_pattern = "(.+)[0-9]")
# A tibble: 9 x 3
    PID     T measurement
  <dbl> <dbl>       <dbl>
1     1     1         100
2     1     4         200
3     1     7          50
4     2     2         150
5     2     5         300
6     2     8          60
7     3     3         120
8     3     6         210
9     3     9          70

names_to = ".value"参数根据names_pattern参数从列名创建新列。 names_pattern参数采用特殊的正则表达式输入。在这种情况下,这是细分:

(.+)  # match everything - anything noted like this becomes the ".values"
[0-9] # numeric characters - tells the pattern that the numbers 
      # at the end are excluded from ".values". If you have multiple digit 
      # numbers,use [0-9*]
,

考虑数据帧,df如下所示:

     PID T1 measurement1 T2 measurement2 T3 measurement3
     1   1          100  4          200  7           50
     2   2          150  5          300  8           60
     3   3          120  6          210  9           70

您可以使用此解决方案获取所需的数据框:

iters = seq(from = 4,to = length(colnames(df))-1,by = 2)
finalDf = df[,c(1,2,3)]
for(j in iters){
    tobind = df[,j,j+1)]
    finalDf = rbind(finalDf,tobind)
}

finalDf = finalDf[order(finalDf[,1]),]

print(finalDf)

print语句的输出是这样的:

   PID T1 measurement1
1   1  1          100
4   1  4          200
7   1  7           50
2   2  2          150
5   2  5          300
8   2  8           60
3   3  3          120
6   3  6          210
9   3  9           70
,

tidyverse解决方案

library(tidyverse)
dw %>% 
  pivot_longer(-PID) %>% 
  mutate(name = gsub('^([A-Za-z]+)(\\d+)$','\\1_\\2',name )) %>% 
  separate(name,into = c('A','B'),sep = '_',convert = T) %>% 
  pivot_wider(names_from = A,values_from = value)

给出以下输出

# A tibble: 9 x 4
    PID     B     T measurement
  <int> <int> <int>       <int>
1     1     1     1         100
2     1     2     4         200
3     1     3     7          50
4     2     1     2         150
5     2     2     5         300
6     2     3     8          60
7     3     1     3         120
8     3     2     6         210
9     3     3     9          70
,

在上一次编辑中,您要求一个易于理解的解决方案。一种非常简单的方法是将测量列彼此堆叠,而将Tdays列彼此堆叠。尽管特殊软件包使事情变得非常简洁和优雅,但为简单起见,我们可以解决此问题而无需其他软件包。标准R有一个方便的函数,恰当地命名为stack,其功能如下:

> exp <-  data.frame(value1 = 1:5,value2 = 6:10)
> stack(exp)
   values    ind
1       1 value1
2       2 value1
3       3 value1
4       4 value1
5       5 value1
6       6 value2
7       7 value2
8       8 value2
9       9 value2
10     10 value2

我们可以分别堆叠测量值和Tday,然后通过cbind将它们组合:

data <- read.table(header=T,text='
  pid     measurement1     Tdays1     measurement2      Tdays2     measurement3     Tdays3  measurement4    Tdays4 
   1         1356           1435         1483            1405         1563           1374       NA           NA     
   2         943            1848         1173            1818         1300           1785       NA           NA     
   3         1590           185          NA              NA           NA             NA         1585         294    
   4         130            72           443             70           NA             NA         136          79     
   4         140            82           NA              NA           NA             NA         756          89     
   4         220            126          266             124          NA             NA         703          128    
   4         166            159          213             156          476            145        776          166    
   4         380            189          583             173          NA             NA         586          203    
   4         353            231          510             222          656            217        526          240    
   4         180            268          NA              NA           NA             NA         NA           NA       
   4         NA             NA           NA              NA           NA             NA         580          278    
   4         571            334          596             303          816            289        483          371    
  ')


cbind(stack(data,c(measurement1,measurement2,measurement3,measurement4)),stack(data,c(Tdays1,Tdays2,Tdays3,Tdays4)))

哪些可以将测量值和Tday整齐地保持在一起,但没有pid,我们可以使用rep将其添加到原始pid中,将其复制4次:

result <- cbind(pid = rep(data$pid,4),Tdays4)))

头部看起来像

> head(result)
  pid values          ind values    ind
1   1   1356 measurement1   1435 Tdays1
2   2    943 measurement1   1848 Tdays1
3   3   1590 measurement1    185 Tdays1
4   4    130 measurement1     72 Tdays1
5   4    140 measurement1     82 Tdays1
6   4    220 measurement1    126 Tdays1

如上所述,这不是您期望的顺序,如果有任何问题,您可以尝试对data.frame进行排序:

result <- result[order(result$pid),4,2)]
names(result) <- c("pid","Time","Value")

导致最终结果

> head(result)
   pid Time Value
1    1 1435  1356
13   1 1405  1483
25   1 1374  1563
37   1   NA    NA
2    2 1848   943
14   2 1818  1173
,

也许您可以像下面那样尝试text

reshape

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。