在tidyr :: extract中使用正则表达式

时间:2017-11-21 22:15:37

标签: r regex tidyr

我正在处理3D动作捕捉数据。这意味着对于身体中的几个关节,我有3列(X,Y,Z)的关节坐标(例如,描述左膝关节中心位置的三列是:LKX,LKY,LKZ)。

我的最终目标是至少绘制9个联合中心,我相信实现这一目标的唯一方法是将我的宽幅数据帧转换为长数据帧。

正如你所知,我试图改变以X:Y或Z结尾的许多联合中心集。因此,我尝试在tidyr:extract中使用正则表达式,但我无法正确使用代码

df_wide <- data.frame(
  ID = rep(1:2, each=10),
  JN = rep(1:2, each=5),
  Frame = rep(1:5, 4),
  System = rep(1:2, 10),
  RKX = rep(1:10+rnorm(10,mean=1,sd=0.5),2),
  RKY = rep(1:10+rnorm(10,mean=1,sd=0.5),2),
  RKZ = rep(1:10+rnorm(10,mean=1,sd=0.5), 2),
  LHeX = rep(1:10-rnorm(10,mean=1,sd=0.5),2),
  LHeY = rep(1:10-rnorm(10,mean=1,sd=0.5),2),
  LHeZ = rep(1:10-rnorm(10,mean=1,sd=0.5),2))

head(df_wide, 2)
  ID JN Frame System      RKX      RKY      RKZ        LHeX       LHeY      LHeZ
1  1  1     1      1 1.332827 2.068720 2.295742 -0.02336031 -0.3011227 -1.212326
2  1  1     2      2 3.570076 3.306799 3.136177  2.08828231  1.9226740  2.106496

我希望得到这个结果:

   ID JN Frame System joint         X         Y         Z
1   1  1     1      1    RK  1.440103  2.221676  1.621871
2   1  1     1      1   LHe  3.537940  3.060948  2.856955

这是我最近的(很多)尝试。它有两个问题; 1)提取物仅产生NA; 2)spread返回“错误:行的重复标识符”我怀疑这与提取问题有关。

df_3D <- df_wide %>%
 gather(keys, values, -ID, -JN, -Frame, -System)%>% 
  extract(keys, c("X", "Y", "Z", "joint"), "(X$) (Y$) (Z$) ([A-Z].$)")%>% 
  spread(X, values)

我找到了几个关于转换的好问题和答案,但没有一个专门针对正则表达式的使用。

2 个答案:

答案 0 :(得分:4)

你的方法有点偏差。收集后keys列的每个元素都具有结构<Joint><Coord>,因此您需要以下内容:

df_wide %>%
    gather(keys, values, -ID, -JN, -Frame, -System) %>%
    extract(keys, c("Joint", "Coord"), "(.*)(X|Y|Z)$") %>%
    spread(Coord, values)

我在这里使用的正则表达式捕获了第一组中的任何内容(因为我不知道所有可能的联名),然后X或Y或Z作为第二组中的最后一个字符。还有很多其他的正则表达式可以达到同样的效果。

输出:

   ID JN Frame System Joint          X          Y           Z
1   1  1     1      1   LHe  0.1344259 -0.2927277  0.05375166
2   1  1     1      1    RK  1.8083539  2.4053498  2.32899399
3   1  1     2      2   LHe  1.1777492  1.1780538  0.96549849
4   1  1     2      2    RK  3.2254236  2.4100235  2.79816371

答案 1 :(得分:2)

您需要将数据收集为超长格式,然后拆分维度,然后将数据传播回X,Y和Z列:

library(tidyr)
library(stringr)

df2  <- df_wide %>% 
  # leave the other columns
  gather( jointid, position, -ID, -JN, -Frame, -System ) %>% 
  # insert a seperator to make it easier to split the X/Y/Z from the joint name
  mutate(jointid = str_replace( jointid, "X|Y|Z", ";\\0")) %>% 
  # split the joint name and the dimension apart
  tidyr::separate(jointid, c('joint', 'dim'), sep = ";" ) %>% 
  # spread the joint and position apart into 3 columns
  spread(dim, position)