在带有变量的 2 行上使用 melt 或 pivot_longer
Using melt or pivot_longer over 2 rows with variables
我的这个输出包含不同 'places' (bel..tej) 中基因家族(例如 family01、family21)的值,但它还包含一些与这些站点相关的元数据(类型环境)。我知道数据没有我希望的那么整齐,所以我想知道是否有一种优雅的方法可以使用 pivot_longer
以长格式整理它以便稍后制作热图。
这是数据集。
Sample bel buc mal man pen poc tej
Environment C_3 C_1 C_3 C_3 C_2 C_1 C_3
family01 1.962 20.790 0.000 0.000 0.000 0.000 1.962
family03 0.000 3.150 0.000 0.000 152.614 0.089 0.000
family08 4.482 12.603 0.168 0.460 0.000 2.917 4.482
family13 0.000 1.697 0.000 0.000 169.841 0.000 0.000
family17 0.462 10.689 0.000 0.000 0.000 1.387 0.462
family21 0.000 0.410 0.000 0.000 122.959 0.000 0.000
我搜索了函数 pivot_longer
的帮助,有几个问题涉及多个 列 而不是 行 而不是关于 'simultaneously' 将函数应用于两组变量。首先我尝试了这个 long <- pivot_longer(data = output.txt, cols = -c(Family), names_to = "site", values_to = "rpkm")
但我得到了这个结果
# A tibble: 49 x 3
Sample site rpkm
<chr> <chr> <chr>
1 Environment bel C_3
2 Environment buc C_1
3 Environment mal C_3
4 Environment man C_3
5 Environment pen C_2
6 Environment poc C_1
7 Environment tej C_3
8 family1 bel 1.962
9 family1 buc 20.790
10 family1 mal 0.000
这是预期的格式
Family site Env rpkm
family1 bel 3 1.962
family1 buc 1 20.790
family1 mal 3 0.000
我想如果第一行不存在我可以做
output.txt %>%
pivot_longer(
-Environment,
names_to = c(".value", "Env"),
names_sep = "_")
为了获得将环境类型存储为变量的列 'Env',然后我需要 'another' 转换为长格式。
我想两个连续的 pivot_longer 轮可以解决这个问题或使用其他策略 melt
(例如,在网站上和网站类型作为前 2 行)。这是一个很长的 table,所以我想避免对其进行排序或手动编辑。
这是dput的输出:
structure(list(Sample = c("Environment", "family01", "family03",
"family08", "family13", "family17", "family21"), bel = c("C__3",
"1.962", "0", "4.482", "0", "0.462", "0"), buc = c("C_1", "20.79",
"3.15", "12.603", "1.697", "10.689", "0.41"), mal = c("C_3",
"0", "0", "0.168", "0", "0", "0"), man = c("C_3", "0", "0", "0.46",
"0", "0", "0"), pen = c("C_2", "0", "152.614", "0", "169.841",
"0", "122.959"), poc = c("C_1", "0", "0.089", "2.917", "0", "1.387",
"0"), tej = c("C_3", "1.962", "0", "4.482", "0", "0.462", "0"
)), row.names = c(NA, -7L), class = c("tbl_df", "tbl", "data.frame"
))
附录 如果有人想使用解决方案,我不得不使用解决方法保存(xlsx 或 csv)并再次加载 tibble 并指定值(rpkm)是数字.
这是一个选项,我们通过 paste
ing (str_c
) 删除 C_
后的第一行元素来更改第一行以外的列名称,然后删除第一行(slice(-1)
),转换 type.convert
列的 type
,从 'wide' 重塑为 'long' (pivot_longer
),separate
通过在小写字母和数字之间的边界处拆分,将 'name' 列一分为二((?<=[a-z])(?=\d)
- 正则表达式环视)
library(dplyr)
library(tidyr)
library(stringr)
output.txt %>%
rename_at(-1, ~ str_c(., unlist(output.txt %>%
slice(1) %>%
select(-Sample) %>%
unlist %>%
str_remove('C_+')))) %>%
slice(-1) %>%
type.convert(as.is = TRUE) %>%
pivot_longer(cols = -Sample, values_to = 'rpkm') %>%
separate(name, into = c('site', 'Env'), sep='(?<=[a-z])(?=\d)')
# A tibble: 42 x 4
# Sample site Env rpkm
# <chr> <chr> <chr> <dbl>
# 1 family01 bel 3 1.96
# 2 family01 buc 1 20.8
# 3 family01 mal 3 0
# 4 family01 man 3 0
# 5 family01 pen 2 0
# 6 family01 poc 1 0
# 7 family01 tej 3 1.96
# 8 family03 bel 3 0
# 9 family03 buc 1 3.15
#10 family03 mal 3 0
# … with 32 more rows
这是另一个与您的想法类似的解决方案。基本上,我将第一行重塑为更长的格式,并对其余行执行相同的操作;然后我在 site
列加入两者。
library(dplyr)
library(tidyr)
library(stringr)
output.txt %>%
slice(1) %>%
pivot_longer(-Sample, names_to = "site", values_to = "Env") %>%
mutate(Env = str_remove(Env, 'C_+')) %>%
select(-Sample) %>%
right_join(.,
{output.txt %>%
slice(-1) %>%
pivot_longer(-Sample, names_to = "site", values_to = "rpkm")},
by = "site") %>%
select(Family = Sample, site, Env, rpkm)
#> # A tibble: 42 x 4
#> Family site Env rpkm
#> <chr> <chr> <chr> <chr>
#> 1 family01 bel 3 1.962
#> 2 family01 buc 1 20.79
#> 3 family01 mal 3 0
#> 4 family01 man 3 0
#> 5 family01 pen 2 0
#> 6 family01 poc 1 0
#> 7 family01 tej 3 1.962
#> 8 family03 bel 3 0
#> 9 family03 buc 1 3.15
#> 10 family03 mal 3 0
#> # ... with 32 more rows