R - 根据列名将列加在一起
R - adding columns together, depending on column name
我有一个数据框 (df1),其中包含每个样本中不同物种的丰度:
> SampleID Sp1 Sp2 Sp3 Sp4 ... Spn
> asb-001 3 0 0 23 9
> asb-002 4 15 10 56 98
> asb-003 8 45 8 453 0
> asb-004 0 5 0 3 6
> asb-005 120 56 0 0 0
...
每一列代表一个不同的物种。
我有另一个数据框 (df2)
Sp Fam
Sp1 Fam1
Sp2 Fam2
Sp3 Fam1
Sp4 Fam3
Sp5 Fam2
Sp6 Fam1
...
家族名称的数量少于物种名称的数量。
我想根据物种名称将列加在一起以获得该科的总数(例如 Sp1 + Sp3 + Sp6 = Fam1)。我不想保留带有物种名称的原始列。
如果一切按计划进行,我的新数据框 (df3) 将如下所示:
> SampleID Fam1 Fam2 Fam3
> asb-001 12 0 9
> asb-002 14 18 112
> asb-003 28 58 18
> asb-004 10 12 10
> asb-005 142 65 0
...
我可以手动遍历并将单个物种添加在一起,但这对于大型数据集来说似乎很乏味,并且可能会产生错误。我有种感觉,我应该融化df1,但我对细节没有信心。任何意见,将不胜感激!
将您的原始数据更改为长格式并加入物种-家族映射。然后,您可以使用 group_by
计算每个家庭的总和。最后,将数据展开为宽格式。
library( tidyverse )
df1 %>% gather( Sp, Value, -SampleID ) %>% # Convert to long format
inner_join( df2 ) %>% # Combine with family mapping
group_by( SampleID, Fam ) %>% # Work on each sample/family pair
summarize( ValSum = sum(Value) ) %>% # Compute the sum across species
ungroup %>% spread( Fam, ValSum, fill=0 ) # Convert back to wide format
根据每个样本是否代表每个家族,您可能会在转换回宽格式后得到 NA
。可选参数 fill=0
负责将这些 NA
转换为 0.
另一种方式,使用library(data.table)
:
setDT(df1); setDT(df2) # Convert data.frames into data.tables
x = df2[melt(df1, variable.name = 'Sp'), on = 'Sp'] # Join melted df1 to df2 on species
df3 = dcast(x, SampleID~Fam, fun.aggregate = sum) # cast to wide format by summing total values per family
我有一个数据框 (df1),其中包含每个样本中不同物种的丰度:
> SampleID Sp1 Sp2 Sp3 Sp4 ... Spn
> asb-001 3 0 0 23 9
> asb-002 4 15 10 56 98
> asb-003 8 45 8 453 0
> asb-004 0 5 0 3 6
> asb-005 120 56 0 0 0
...
每一列代表一个不同的物种。
我有另一个数据框 (df2)
Sp Fam
Sp1 Fam1
Sp2 Fam2
Sp3 Fam1
Sp4 Fam3
Sp5 Fam2
Sp6 Fam1
...
家族名称的数量少于物种名称的数量。
我想根据物种名称将列加在一起以获得该科的总数(例如 Sp1 + Sp3 + Sp6 = Fam1)。我不想保留带有物种名称的原始列。
如果一切按计划进行,我的新数据框 (df3) 将如下所示:
> SampleID Fam1 Fam2 Fam3
> asb-001 12 0 9
> asb-002 14 18 112
> asb-003 28 58 18
> asb-004 10 12 10
> asb-005 142 65 0
...
我可以手动遍历并将单个物种添加在一起,但这对于大型数据集来说似乎很乏味,并且可能会产生错误。我有种感觉,我应该融化df1,但我对细节没有信心。任何意见,将不胜感激!
将您的原始数据更改为长格式并加入物种-家族映射。然后,您可以使用 group_by
计算每个家庭的总和。最后,将数据展开为宽格式。
library( tidyverse )
df1 %>% gather( Sp, Value, -SampleID ) %>% # Convert to long format
inner_join( df2 ) %>% # Combine with family mapping
group_by( SampleID, Fam ) %>% # Work on each sample/family pair
summarize( ValSum = sum(Value) ) %>% # Compute the sum across species
ungroup %>% spread( Fam, ValSum, fill=0 ) # Convert back to wide format
根据每个样本是否代表每个家族,您可能会在转换回宽格式后得到 NA
。可选参数 fill=0
负责将这些 NA
转换为 0.
另一种方式,使用library(data.table)
:
setDT(df1); setDT(df2) # Convert data.frames into data.tables
x = df2[melt(df1, variable.name = 'Sp'), on = 'Sp'] # Join melted df1 to df2 on species
df3 = dcast(x, SampleID~Fam, fun.aggregate = sum) # cast to wide format by summing total values per family