Получить имя столбца, в котором выполняется условие после суммирования до n столбцов - PullRequest
0 голосов
/ 01 июля 2019

У меня есть данные ниже, которые содержат ежемесячные продажи разных продавцов

df_monthofsuccess
M1_Sales    M2_Sales    M3_Sales    M4_Sales    M5_Sales    M6_Sales
15000       16435       12144       55536       75260       15002
35853       41020       66689       0           51495       11725
2500        24600       0   0       3000        0           12445
80654       0           50625       275946      37320       43000
21578       40000       0   0       20000       0   0       20000

Я хочу узнать месяц, в котором они достигли 1 000 000, и записать этот месяц в отдельной переменной, как показано ниже

M1_Sales    M2_Sales    M3_Sales    M4_Sales    M5_Sales    M6_Sales Month_Target
15000       16435       12144       55536       75260       15002       M5
35853       41020       66689       0           51495       11725       M3
2500        24600       0   0       3000        0           12445       FALSE
80654       0           50625       275946      37320       43000       M3
21578       40000       0   0       20000       0   0       20000       M6

Я пробовал с кодом ниже:

df_success <- data.frame()
for (i in (1:nrow(df_monthofsuccess))){
  #i = 9
  x <- df_monthofsuccess[i,]
  ape_tot = 0
  month = 'FALSE'
  for (j in (2:ncol(x))){
    #j = 2
    ape_tot = ape_tot + x[,j]
    if (ape_tot > 100000) month = names(x)[j]
    x$monthofSuccess <- month
    next
  }
  df_success <- rbind(df_success,x)
}

Однако, это не дает ожидаемый результат и является медленным.

Может ли кто-нибудь помочь мне в достижении желаемого результата?

Ответы [ 2 ]

0 голосов
/ 01 июля 2019

A tidyverse подход может заключаться в gather данных в длинном формате, group_by каждый row находит month_name, когда кумулятивные значения sales достигают 100000 и spread обратноформат.

library(dplyr)
library(tidyr)

df %>%
  mutate(row = row_number()) %>%
  gather(month, sales, -row) %>%
  mutate(month_name = sub("_.*", "", month)) %>%
  group_by(row) %>%
  mutate(target = month_name[which(cumsum(sales) > 100000)[1]]) %>%
  select(-month_name) %>%
  spread(month, sales) %>%
  ungroup() %>%
  select(-row)

#  target M1_Sales M2_Sales M3_Sales M4_Sales M5_Sales M6_Sales
#  <chr>     <int>    <int>    <int>    <int>    <int>    <int>
#1 M5        15000    16435    12144    55536    75260    15002
#2 M3        35853    41020    66689        0    51495    11725
#3 NA         2500    24600        0     3000        0    12445
#4 M3        80654        0    50625   275946    37320    43000
#5 M6        21578    40000        0    20000        0    20000
0 голосов
/ 01 июля 2019

Мы можем использовать apply для циклического перебора строк в base R, получить индекс столбца, в котором кумулятивная сумма строки больше 1e5, извлечь names первого элемента

df1$Month_Target <- apply(df1, 1, FUN = function(x) sub("_Sales", "", 
         names(which(cumsum(x) >1e5)[1])))
df1$Month_Target
#[1] "M5" "M3" NA   "M3" "M6"

ПРИМЕЧАНИЕ: пакеты не используются. Только base R


Или используя векторизованный подход с matrixStats

library(matrixStats)
m1 <- rowCumsums(as.matrix(df1)) 
substr(names(df1), 1, 2)[max.col(m1 > 1e5, "first") * NA^!(rowSums(m1 > 1e5))]
#[1] "M5" "M3" NA   "M3" "M6"

Или с помощью tidyverse без изменения формы

library(tidyverse)
df1 %>%
    mutate(Month_Target = pmap(., ~ 
         names(which(cumsum(c(...)) >1e5)[1])) %>%
            str_remove("_Sales"))
#  M1_Sales M2_Sales M3_Sales M4_Sales M5_Sales M6_Sales Month_Target
#1    15000    16435    12144    55536    75260    15002           M5
#2    35853    41020    66689        0    51495    11725           M3
#3     2500    24600        0     3000        0    12445         <NA>
#4    80654        0    50625   275946    37320    43000           M3
#5    21578    40000        0    20000        0    20000           M6

данные

df1 <- structure(list(M1_Sales = c(15000L, 35853L, 2500L, 80654L, 21578L
), M2_Sales = c(16435L, 41020L, 24600L, 0L, 40000L), M3_Sales = c(12144L, 
66689L, 0L, 50625L, 0L), M4_Sales = c(55536L, 0L, 3000L, 275946L, 
20000L), M5_Sales = c(75260L, 51495L, 0L, 37320L, 0L), M6_Sales = c(15002L, 
11725L, 12445L, 43000L, 20000L)), class = "data.frame", row.names = c(NA, 
-5L))
...