Как суммировать столбец из нескольких наборов данных, которые не имеют одинаковую структуру? - PullRequest
2 голосов
/ 20 мая 2019

У меня есть несколько файлов (20) с одинаковой структурой столбцов, но с разной структурой строк. Все они состоят из двух столбцов: первый - это множители, а второй - целые числа. Я хочу суммировать столбец целых чисел для повторяющихся факторов и новых, которые просто добавляются. Как я могу объединить и суммировать уже повторенные?

Я думал о комбинировании cbind и tapply, но я действительно не знаю, как это осуществить.

Простой пример структуры файлов:

Shop   Clients     Shop  Clients     Shop Clients
 A        9          D      8          A     5
 B        7          A      4          R     4
 C        4          F      3          C     3
 D        2          B      1          B     2

Я ожидаю выхода:

Shop Clients
A      18 
B      10
C       7
D      10
F       3
R       4

Я читаю различные файлы в цикле, создавая набор данных для каждого из них, так что набор данных показывает, например, City1 $ Shop и City1 $ Clients. Этот случай только для 20 файлов, но я хотел бы знать, как работать с более (например, 100). Как я мог решить эту проблему, читая наборы данных таким образом?

f<-function(x){
  read.delim2("p01.txt",header=T,sep="\t",stringsAsFactors = FALSE)
}
for(i in x){
total<-f(i)
#Here I suppose I would combine and sum the datasets
}

Ответы [ 3 ]

1 голос
/ 20 мая 2019

Можно использовать aggregate после преобразования данных в длинный формат.

inx <- grep("Shop", names(df1))
long <- do.call(rbind, lapply(inx, function(i) df1[i:(i + 1)]))
aggregate(Clients ~ Shop, long, sum)
#  Shop Clients
#1    A      18
#2    B      10
#3    C       7
#4    D      10
#5    F       3
#6    R       4

Редактировать.
После редактирования вопроса, я полагаю, что следующее делает то, что спрашивают. Я еще раз буду использовать aggregate.

fnames <- list.files(pattern = "\\.txt")
df_list <- lapply(fnames, read.table, header = TRUE)
df_all <- do.call(rbind, df_list)
aggregate(Clients ~ Shop, data = df_all, sum)
1 голос
/ 20 мая 2019

Одна tidyverse возможность может быть:

df %>%
 select_at(vars(contains("Shop"))) %>%
 gather(var1, val1) %>%
 bind_cols(df %>%
 select_at(vars(contains("Client"))) %>%
 gather(var2, val2)) %>%
 group_by(Shop = val1) %>%
 summarise(Clients = sum(val2))

  Shop  Clients
  <chr>   <int>
1 A          18
2 B          10
3 C           7
4 D          10
5 F           3
6 R           4

То же самое с base R:

long_df <- data.frame(Shop = stack(df[, grepl("Shop", names(df))])[, 1], 
Clients = stack(df[, grepl("Client", names(df))])[, 1])
aggregate(Clients ~ Shop, long_df, sum)

  Shop Clients
1    A      18
2    B      10
3    C       7
4    D      10
5    F       3
6    R       4
1 голос
/ 20 мая 2019

Мы можем melt данных в «длинном» формате, указав столбцы measure с именами столбцов patterns как «Магазин», «Клиенты», а затем сгруппированные по «Магазину» получить sum из ' Клиенты

library(data.table)
melt(setDT(df1), measure = patterns("^Shop", "^Clients"), 
  value.name = c("Shop", "Clients"))[, .(Clients = sum(Clients)), by = Shop]
#    Shop Clients
#1:    A      18
#2:    B      10
#3:    C       7
#4:    D      10
#5:    F       3
#6:    R       4

Или используя tidyverse

library(tidyverse)
map_dfc(list(Shop = "Shop", Clients = "Clients"), ~
    df1 %>%
       select(matches(.x)) %>% 
       unlist) %>% 
  group_by(Shop) %>% 
  summarise(Clients = sum(Clients))
# A tibble: 6 x 2
#  Shop  Clients
#  <chr>   <int>
#1 A          18
#2 B          10
#3 C           7
#4 D          10
#5 F           3
#6 R           4

Или с rowsum из base R

i1 <- grepl("^Shop", names(df1))
rowsum(unlist(df1[!i1]), group =  unlist(df1[i1]))

данные

df1 <- structure(list(Shop = c("A", "B", "C", "D"), Clients = c(9L, 
 7L, 4L, 2L), Shop.1 = c("D", "A", "F", "B"), Clients.1 = c(8L, 
 4L, 3L, 1L), Shop.2 = c("A", "R", "C", "B"), Clients.2 = 5:2), 
  class = "data.frame", row.names = c(NA, -4L))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...