Я пытаюсь подготовить свои данные, и у меня возникла одна проблема. Допустим, у меня есть следующий фрейм данных:

df1
Name    C1    Val1
A       a       x1
A       a       x2
A       b       x3
A       c       x4
B       d       x5
B       d       x6
...

И я хочу сузить df до

df2
Name    C1     Val
A       a,b,c  x1+x2+x3+x4
B       d      x5+x6
...

В то время как a - символьное значение, а x - числовое значение Я пытался использовать sapply, rowsum и df2<- aggregate(df1, list(df1[,1]), FUN= summary) но он просто не может поместить значения символов в список для каждого имени.

Может кто поможет мне получить df2?

0
antonina 6 Дек 2019 в 22:01

3 ответа

m <- function(x) if(is.numeric(x<- type.convert(x)))sum(x) else toString(unique(x))
aggregate(.~Name,df1,m)
  Name      C1 Val1
1    A a, b, c   10
2    B       d   11

Где

df1
Name C1 Val1
1    A  a    1
2    A  a    2
3    A  b    3
4    A  c    4
5    B  d    5
6    B  d    6
1
Onyambu 6 Дек 2019 в 22:12
Как я могу отметить, что строки с NA не удаляются?
 – 
antonina
6 Дек 2019 в 22:30
Используйте aggregate(.~Name,df1,m,na.action = identity), в этом случае вам даже нужно изменить функцию m, чтобы использовать na.rm=TRUE в функции sum
 – 
Onyambu
6 Дек 2019 в 22:53

Это ваш df, я даю ему номера от 1 до 6 в Val1

df <-
structure(list(Name = structure(c(1L, 1L, 1L, 1L, 2L, 2L), .Label = c("A", 
"B"), class = "factor"), C1 = structure(c(1L, 1L, 2L, 3L, 4L, 
4L), .Label = c("a", "b", "c", "d"), class = "factor"), Val1 = 1:6), row.names = c(NA, 
-6L), class = "data.frame")

Мы просто используем summarize:

df %>% 
group_by(Name) %>% 
summarise(C1=paste(unique(C1),collapse=","),Val1=sum(Val1))

# A tibble: 2 x 3
  Name  C1     Val1
  <fct> <chr> <int>
1 A     a,b,c    10
2 B     d        11
0
StupidWolf 7 Дек 2019 в 02:48

Быстрое и простое решение dplyr:

    library(dplyr)
library(stringr)
df1 %>%
  mutate(Val1_num = as.numeric(str_extract(Val1, "\\d+"))) %>% 
  group_by(Name) %>% 
  summarise(C1 = paste(unique(C1), collapse = ","),
            Val1 = paste(unique(Val1), collapse = "+"),
            Val1_num = sum(Val1_num))
#> # A tibble: 2 x 4
#>   Name  C1    Val1        Val1_num
#>   <chr> <chr> <chr>          <dbl>
#> 1 A     a,b,c x1+x2+x3+x4       10
#> 2 B     d     x5+x6             11

Или в базе:

df2 <- aggregate(df1, list(df1[,1]), FUN = function(x) {
  if (all(grepl("\\d", x))) {
    sum(as.numeric(gsub("[^[:digit:]]", "", x)))
  } else {
    paste(unique(x), collapse = ",")
  }
}) 

df2
#>   Group.1 Name    C1 Val1
#> 1       A    A a,b,c   10
#> 2       B    B     d   11

Данные

df1 <- read.csv(text = "
Name,C1,Val1
A,a,x1
A,a,x2
A,b,x3
A,c,x4
B,d,x5
B,d,x6", stringsAsFactors = FALSE)
0
JBGruber 7 Дек 2019 в 14:46
Для значений Val1 в df2 я ищу фактическую сумму числовых значений. Как изменить, чтобы получить сумму?
 – 
antonina
6 Дек 2019 в 22:41
Я не понял этого из вопроса! Но проверьте еще раз, я обновил ответ.
 – 
JBGruber
7 Дек 2019 в 14:47