R Сумма чисел в строке - PullRequest
       1

R Сумма чисел в строке

0 голосов
/ 05 февраля 2019

У меня есть вопрос:

У меня есть набор данных, подобный этому простому примеру:

df<-data.frame(ID=c("A","B","C","D"),
               Score=c("15","16/18/19+2/6","3/+2","19/18/14"))

Я хочу получить набор данных, который разделил числа score.У меня проблема с частью /+2.когда он говорит "3/+2", это на самом деле означает: "3/3+2", что в конечном итоге даст "3/5".Так что я хотел бы получить некоторую помощь, чтобы получить такой набор данных:

  ID         Score
  A            15
  B 16/18/19/21/6
  C           3/5
  D      19/18/14

Я уже понял, что могу затем разделить счет на

df<-df %>% 
  mutate(Score = strsplit(as.character(ID), "/")) %>%
  unnest(Score)

НоЯ не знаю, как я могу позволить дублировать числа и затем суммировать, когда происходит + +, кто-то может мне помочь?

Ответы [ 3 ]

0 голосов
/ 05 февраля 2019
library(dplyr)
library(tidyr) #separate_rows, no need for unnest
df %>% rowwise()%>% 
       mutate(Score_upd=paste0(sapply(unlist(strsplit(gsub('(\\d+)/*\\+(\\d+)','\\1/\\1+\\2',Score),'/')),
       function(x)eval(parse(text = x))),collapse = '/')) %>% 
       separate_rows(Score_upd,sep = '/')

#short version
df %>% mutate(Score=gsub('(\\d+)/*\\+(\\d+)','\\1/\\1+\\2',Score)) %>% 
       separate_rows(Score,sep='/') %>% rowwise() %>% mutate(Score=eval(parse(text=Score))) %>% 
       group_by(ID) %>% summarise(Score=paste0(Score,collapse = '/'))

# A tibble: 4 x 2
  ID    Score        
  <fct> <chr>        
  1 A     15           
  2 B     16/18/19/21/6
  3 C     3/5          
  4 D     19/18/14

Основная идея заключается в использовании gsub для правильного разделения 2+3, например:

gsub('(\\d+)/*\\+(\\d+)','\\1/\\1+\\2','20/8/2+3') #/* means 0 or 1 occurence of / e.g, 19+2 and 3/+2.
[1] "20/8/2/2+3"

Тогда

valid_str <- gsub('(\\d+)/*\\+(\\d+)','\\1/\\1+\\2','20/8/2+3')
sapply(unlist(strsplit(valid_str,'/')),function(x) eval(parse(text=x)))
20   8   2 2+3 
20   8   2   5 
#OR
sapply(unlist(strsplit(valid_str,'/')),function(x) sum(as.numeric(unlist(strsplit(x,'\\+')))))
20   8   2 2+3 
20   8   2   5
0 голосов
/ 05 февраля 2019

Мы можем использовать gsubfn, чтобы сделать это компактным образом

library(gsubfn)
library(tidyverse)
df %>% 
   mutate(Score = gsubfn("\\d+\\+\\d+", ~ eval(parse(text = x)), Score))
# ID      Score
#1  A         15
#2  B 16/18/21/6
#3  C        3/5
#4  D   19/18/14

data

df <- data.frame(ID=c("A","B","C","D"),
           Score=c("15","16/18/19+2/6","3/3+2","19/18/14"), stringsAsFactors = FALSE)
0 голосов
/ 05 февраля 2019

Вероятно, это может быть решено более элегантным способом, но есть одна возможность:

df %>%
 mutate(Score = strsplit(as.character(Score), "/")) %>%
 unnest() %>%
 rowwise() %>%
 mutate(Score = eval(parse(text = paste0(Score)))) %>%
 group_by(ID) %>%
 mutate(Score = paste0(Score, collapse = "/")) %>%
 distinct()

  ID    Score     
  <fct> <chr>     
1 A     15        
2 B     16/18/21/6
3 C     3/5       
4 D     19/18/14  

Образцы данных:

df <- data.frame(ID=c("A","B","C","D"),
               Score=c("15","16/18/19+2/6","3/3+2","19/18/14"))

Разбивает «Оценка» на основе /,преобразует символы в выражение с помощью parse(), а затем преобразует его обратно.

Используя предоставленные вами данные и шаблон из @A.Сулиман:

df %>%
 mutate(Score = strsplit(gsub("(\\d+)/*\\+(\\d+)","\\1/\\1+\\2", Score), "/")) %>%
 unnest() %>%
 rowwise() %>%
 mutate(Score = eval(parse(text = paste0(Score)))) %>%
 group_by(ID) %>%
 mutate(Score = paste0(Score, collapse = "/")) %>%
 distinct()

  ID    Score        
  <fct> <chr>        
1 A     15           
2 B     16/18/19/21/6
3 C     3/5          
4 D     19/18/14 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...