从宽到长的正则表达式 R
Wide to Long Form Regex R
我正在尝试使用 tidyr 将数据从宽格式转换为长格式,但也可以使用其他选项。这是具有重复值的假数据集,但它与真实数据集具有相同的结构
structure(list(Category = c("Pre", "Pre", "Pre", "post_med_1",
"post_med_1", "post_med_1", "post_med_2", "post_med_2", "post_med_2"
), Time = c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L), Subj_1_tox = c(4.2,
5, 2.3, 4.2, 5, 2.3, 4.2, 5, 2.3), Subj_2_tox = c(23L, 1L, 4L,
23L, 1L, 4L, 23L, 1L, 4L), Subj_3_tox = c(6, 4.9, 3.2, 6, 4.9,
3.2, 6, 4.9, 3.2), Subj_1_a1 = c(4.2, 5, 2.3, 4.2, 5, 2.3, 4.2,
5, 2.3), Subj_2_a1 = c(23L, 1L, 4L, 23L, 1L, 4L, 23L, 1L, 4L),
Subj_3_a1 = c(6, 4.9, 3.2, 6, 4.9, 3.2, 6, 4.9, 3.2)), class = "data.frame", row.names = c(NA,
-9L))
让我感到困惑的部分是如何在一次调用中将 tox 列和 a1 列转换为长格式并维护类别和时间列。首先是名称模式的正则表达式。我查找了正则表达式模式,但不清楚如何获取它,其次如何在 1 个调用中包含 2 个不同的值列?
基本上一个电话就这样
df_longer<-df %>%
pivot_longer(
cols=contains("tox") & contains("a1"),
names_to = c("subject", "tox", "a1"),
names_pattern = "(Subj_['all_numbers') (tox and a1) "
values_to = c("tox_value", "a1"))
最终结果是 Subject(#) 在一个名为 subject 的列中,tox 值和 a1 值在其他列中。是否有可能在一个电话中做到这一点?我也对其他解决方案持开放态度,但正在努力学习更多 tidyr
最终结果应该是这样的,但是这个值不对,但其他部分是准确的。
如果我对您的 post 理解正确,那么这在一行中是可能的。请参阅下面我的解决方案,
# load library;
library(tidyverse)
# Store data;
tmpData <- structure(
list(
Category = c(
"Pre",
"Pre",
"Pre",
"post_med_1",
"post_med_1",
"post_med_1",
"post_med_2",
"post_med_2",
"post_med_2"
),
Time = c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L),
Subj_1_tox = c(4.2,
5, 2.3, 4.2, 5, 2.3, 4.2, 5, 2.3),
Subj_2_tox = c(23L, 1L, 4L,
23L, 1L, 4L, 23L, 1L, 4L),
Subj_3_tox = c(6, 4.9, 3.2, 6, 4.9,
3.2, 6, 4.9, 3.2),
Subj_1_a1 = c(4.2, 5, 2.3, 4.2, 5, 2.3, 4.2,
5, 2.3),
Subj_2_a1 = c(23L, 1L, 4L, 23L, 1L, 4L, 23L, 1L, 4L),
Subj_3_a1 = c(6, 4.9, 3.2, 6, 4.9, 3.2, 6, 4.9, 3.2)
),
class = "data.frame",
row.names = c(NA,
-9L)
)
# Pivot longer;
tmpData %>% pivot_longer(cols = contains("Subj"),
names_to = "subject")
如果您的列有共同的和不同的前缀,您不一定需要 regex
,就像您的数据一样,您需要的所有列都以 Subj
开头。因此,您可以只使用 dplyr
.
中的 contains()
如果我误解了你的问题,请告诉我。
您可以使用 names_to
和 names_pattern
作为 -
tidyr::pivot_longer(df,
cols = starts_with("Subj"),
names_to = c("subject", ".value"),
names_pattern = "(Subj_\d+)_(.*)")
# Category Time subject tox a1
# <chr> <int> <chr> <dbl> <dbl>
# 1 Pre 1 Subj_1 4.2 4.2
# 2 Pre 1 Subj_2 23 23
# 3 Pre 1 Subj_3 6 6
# 4 Pre 2 Subj_1 5 5
# 5 Pre 2 Subj_2 1 1
# 6 Pre 2 Subj_3 4.9 4.9
# 7 Pre 3 Subj_1 2.3 2.3
# 8 Pre 3 Subj_2 4 4
# 9 Pre 3 Subj_3 3.2 3.2
#10 post_med_1 1 Subj_1 4.2 4.2
# … with 17 more rows
我正在尝试使用 tidyr 将数据从宽格式转换为长格式,但也可以使用其他选项。这是具有重复值的假数据集,但它与真实数据集具有相同的结构
structure(list(Category = c("Pre", "Pre", "Pre", "post_med_1",
"post_med_1", "post_med_1", "post_med_2", "post_med_2", "post_med_2"
), Time = c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L), Subj_1_tox = c(4.2,
5, 2.3, 4.2, 5, 2.3, 4.2, 5, 2.3), Subj_2_tox = c(23L, 1L, 4L,
23L, 1L, 4L, 23L, 1L, 4L), Subj_3_tox = c(6, 4.9, 3.2, 6, 4.9,
3.2, 6, 4.9, 3.2), Subj_1_a1 = c(4.2, 5, 2.3, 4.2, 5, 2.3, 4.2,
5, 2.3), Subj_2_a1 = c(23L, 1L, 4L, 23L, 1L, 4L, 23L, 1L, 4L),
Subj_3_a1 = c(6, 4.9, 3.2, 6, 4.9, 3.2, 6, 4.9, 3.2)), class = "data.frame", row.names = c(NA,
-9L))
让我感到困惑的部分是如何在一次调用中将 tox 列和 a1 列转换为长格式并维护类别和时间列。首先是名称模式的正则表达式。我查找了正则表达式模式,但不清楚如何获取它,其次如何在 1 个调用中包含 2 个不同的值列?
基本上一个电话就这样
df_longer<-df %>%
pivot_longer(
cols=contains("tox") & contains("a1"),
names_to = c("subject", "tox", "a1"),
names_pattern = "(Subj_['all_numbers') (tox and a1) "
values_to = c("tox_value", "a1"))
最终结果是 Subject(#) 在一个名为 subject 的列中,tox 值和 a1 值在其他列中。是否有可能在一个电话中做到这一点?我也对其他解决方案持开放态度,但正在努力学习更多 tidyr
最终结果应该是这样的,但是这个值不对,但其他部分是准确的。
如果我对您的 post 理解正确,那么这在一行中是可能的。请参阅下面我的解决方案,
# load library;
library(tidyverse)
# Store data;
tmpData <- structure(
list(
Category = c(
"Pre",
"Pre",
"Pre",
"post_med_1",
"post_med_1",
"post_med_1",
"post_med_2",
"post_med_2",
"post_med_2"
),
Time = c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L),
Subj_1_tox = c(4.2,
5, 2.3, 4.2, 5, 2.3, 4.2, 5, 2.3),
Subj_2_tox = c(23L, 1L, 4L,
23L, 1L, 4L, 23L, 1L, 4L),
Subj_3_tox = c(6, 4.9, 3.2, 6, 4.9,
3.2, 6, 4.9, 3.2),
Subj_1_a1 = c(4.2, 5, 2.3, 4.2, 5, 2.3, 4.2,
5, 2.3),
Subj_2_a1 = c(23L, 1L, 4L, 23L, 1L, 4L, 23L, 1L, 4L),
Subj_3_a1 = c(6, 4.9, 3.2, 6, 4.9, 3.2, 6, 4.9, 3.2)
),
class = "data.frame",
row.names = c(NA,
-9L)
)
# Pivot longer;
tmpData %>% pivot_longer(cols = contains("Subj"),
names_to = "subject")
如果您的列有共同的和不同的前缀,您不一定需要 regex
,就像您的数据一样,您需要的所有列都以 Subj
开头。因此,您可以只使用 dplyr
.
contains()
如果我误解了你的问题,请告诉我。
您可以使用 names_to
和 names_pattern
作为 -
tidyr::pivot_longer(df,
cols = starts_with("Subj"),
names_to = c("subject", ".value"),
names_pattern = "(Subj_\d+)_(.*)")
# Category Time subject tox a1
# <chr> <int> <chr> <dbl> <dbl>
# 1 Pre 1 Subj_1 4.2 4.2
# 2 Pre 1 Subj_2 23 23
# 3 Pre 1 Subj_3 6 6
# 4 Pre 2 Subj_1 5 5
# 5 Pre 2 Subj_2 1 1
# 6 Pre 2 Subj_3 4.9 4.9
# 7 Pre 3 Subj_1 2.3 2.3
# 8 Pre 3 Subj_2 4 4
# 9 Pre 3 Subj_3 3.2 3.2
#10 post_med_1 1 Subj_1 4.2 4.2
# … with 17 more rows