在同一数据框中连接名称相似的列

时间:2019-08-12 12:09:06

标签: r

我正在处理几种物种的植物覆盖数据,其中一些具有相同的属。数据集的每一列都是一个物种,每一行都是一个采样点。我只需要属下的覆盖数据,我想对同一属下的那些物种的列求和。

我有类似的东西,但种类更多:

df<-data.frame('Abies.alba'= c(0, 1, 0, 0, 1), 'Acer.opalus'= c(0, 0, 1, 1, 1),
               'Acer.campestre'= c(1, 0 , 1, 1, 0), 'Pinus.sylvestris'= c(1, 1, 1, 1, 1),
               'Pinus.uncinata'= c(0, 0, 1, 0, 0))

我想有类似的东西:

df2<-data.frame('Abies'= c(0, 1, 0, 0, 1), 'Acer'= c(1, 0, 2, 2, 1),
               'Pinus'= c(1, 1, 2, 1, 1))

我的主要问题是我有很多不同的属要加入。我曾考虑过转置数据框并汇总行,这是我以前做过的,但我觉得必须有一种更好的方法。

3 个答案:

答案 0 :(得分:2)

通过基数R的想法是拆分共栏名称,并使用grepl查找相似的名称,即

sapply(unique(gsub('\\..*', '', names(df))), function(i)rowSums(df[grepl(i, names(df))]))
#     Abies Acer Pinus
#[1,]     0    1     1
#[2,]     1    0     1
#[3,]     0    2     2
#[4,]     0    2     1
#[5,]     1    1     1

答案 1 :(得分:1)

请考虑将数据的形状从宽变长(在几乎每种分析方法中都是首选格式),然后按时期清除物种字段的列。从那里运行所需的总和。

rdf <- reshape(df, varying = list(names(df)), v.names = "value", 
               times = names(df), timevar="species", 
               new.row.names = 1:1E6, direction = "long")

rdf$genus <- gsub("\\..*", "", rdf$species)
rdf$species <- gsub(".*\\.", "", rdf$species)

head(rdf)
#   species value id genus
# 1    alba     0  1 Abies
# 2    alba     1  2 Abies
# 3    alba     0  3 Abies
# 4    alba     0  4 Abies
# 5    alba     1  5 Abies
# 6  opalus     0  1  Acer

aggdf <- aggregate(value ~ genus, rdf, sum)

aggdf
#   genus value
# 1 Abies     2
# 2  Acer     6
# 3 Pinus     6

Rextester demo

答案 2 :(得分:1)

总的来说,我确实认为像您所说的那样转置数据更有意义。这将帮助您利用R的矢量化操作,该操作最适合“整洁”的数据(https://cran.r-project.org/web/packages/tidyr/vignettes/tidy-data.html)。这就是我的方法:

library(tidyverse)

df %>%
 rowid_to_column() %>%
 gather(species, count, 2:6) %>%
 mutate(species = str_replace(species, "(?=\\.).+", "")) %>%
 group_by(rowid, species) %>%
 summarise(count = sum(count))

# which gets you

# A tibble: 15 x 3
# Groups:   rowid [5]
   rowid species count
   <int> <chr>   <dbl>
 1     1 Abies       0
 2     1 Acer        1
 3     1 Pinus       1
 4     2 Abies       1
 5     2 Acer        0
 6     2 Pinus       1
 7     3 Abies       0
 8     3 Acer        2
 9     3 Pinus       2
10     4 Abies       0
11     4 Acer        2
12     4 Pinus       1
13     5 Abies       1
14     5 Acer        1
15     5 Pinus       1

如果您真的想在列中输入属信息,则可以添加以下行:


df %>%
 rowid_to_column() %>%
 gather(species, count, 2:6) %>%
 mutate(species = str_replace(species, "(?=\\.).+", "")) %>%
 group_by(rowid, species) %>%
 summarise(count = sum(count)) %>%
 ungroup() %>%  
 spread(species, count) %>%
 select(-rowid)