#r #list #function #loops
#r #Список #функция #циклы
Вопрос:
У меня есть список продавцов в трех столбцах, и я хочу перейти к списку, который у меня есть, и:
а) Где их имя отображается в любом из трех столбцов
б) их имя отображается с продавцом-стажером (это будут люди, чьего имени нет в списке)
ilist <- c("SP1","SP2","SP3","SP4","SP5")
df2 <-
data.frame(sales1 = c("SP5","SP5","SP4","SP3","SP2","SP1","SP3"),
sales2 = c("","SP4","SP1","SP1","SP5","SP3",""),
sales3 = c("","SP9","","SP6","","",""))
Вывод Я бы ожидал чего-то вроде приведенного ниже ответа (хотя я бы принял любой вывод):
A B
SP1 3 1
SP2 1 0
SP3 3 1
SP4 1 1
SP5 3 1
Я пытался создать цикл и функцию, но, похоже, я не могу заставить их работать.
Цель после запуска этой работы — сделать ее частью group_by
, чтобы я мог разбить ее по типу и году
data %>%
group_by(type,year) %>%
your helpful answer here
Редактировать:
select
из столбцов, которые я собираюсь использовать.
Мой список будет выглядеть примерно так, как показано ниже
(в 3 столбцах столбцы 2 и 3 будут содержать пробелы, где продавец отображается только в столбце 1; также не задано место размещения, где может появиться продавец или стажер).
ilist <- c("SJ","KW","MOLC","FERB","BACC")
structure(list(iYear = structure(c(1L, 4L, 3L, 4L, 4L,
4L, 5L, 5L, 6L, 9L), .Label = c("2020-07-01", "2020-07-02", "2020-07-03",
"2020-07-04", "2020-07-06", "2020-07-07", "2020-07-08", "2020-07-09",
"2020-07-10", "2020-07-11", "2020-07-12", "2020-07-13", "2020-07-14",
"2020-07-15", "2020-07-16", "2020-07-17", "2020-07-18", "2020-07-19",
"2020-07-20", "2020-07-21", "2020-07-22", "2020-07-23", "2020-07-24",
"2020-07-25", "2020-07-27", "2020-07-28", "2020-07-29", "2020-07-30",
"2020-07-31"), class = "factor"), iType = structure(c(4L,
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L), .Label = c("", "ZB", "BS",
"CFN", "CTR", "MJ", "UK", "EFH", "ENOC", "EY", "F", "G", "CD",
"HAEM", "HN", "IC", "LB", "LY", "MNN", "MOS", "NERO", "ZZZ",
"ZZZQE", "GFT", "PG", "RE", "SK", "UR"), class = "factor"),
Sales.1 = structure(c(74L, 20L, 74L, 16L,
3L, 3L, 3L, 16L, 58L, 41L), .Label = c("", "ABUE", "AHMEM",
"AJOS", "ANNS", "AOK", "BACC", "BH", "BLAFM", "BLOCA", "BRAD",
"BROWNJ", "BRT", "BUIH", "BURDA", "BURYA", "CANRJ", "CAVM",
"CHAMBA", "COOSNP", "COUPSI", "CPH", "CTT", "DARA", "DILP",
"EXPAT", "FCH", "FERB", "FERMA", "GT", "GT", "HAEM", "HAMJR",
"HENJ", "HENJA", "HOWRA", "HUSA", "ILINC", "JONG", "KC",
"KNOT", "KW", "LAUC", "LOOP", "LYEJO", "LYNN", "MAJJ", "MCGREA",
"MENT", "MKB", "MOLC", "MUDHS", "MULLM", "NC", "NODS",
"O'BSG", "OLIT", "OLIVK", "PAEI", "PARKD", "PATEF", "PERT",
"POL", "PTRHUS", "RAMACN", "RAMS", "REYMA", "ROBCM", "ROBINE",
"SAMJN", "SAYC", "SHARMM", "SHEG", "SJ", "SJN", "SKINT",
"SLOP", "SORT", "SOUBIO", "SPOE", "TELED", "THAN", "THEL",
"TURH", "TURHJ", "UCONS", "UPH", "UT", "VALK", "WALJ"
), class = "factor"), Sales.2 = structure(c(1L,
12L, 1L, 1L, 1L, 1L, 1L, 1L, 3L, 45L), .Label = c("", "ABUE",
"AHMEM", "AJOS", "AOK", "BACC", "BH", "BLAFM", "BROWNJ",
"BUIH", "BURDA", "BURYA", "CANRJ", "CAVM", "CHAMBA", "COOSNP",
"COUPSI", "DARA", "DILP", "FCH", "FERB", "FERMA", "GYNT",
"HOWRA", "HUSA", "ILINC", "KW", "LAUC", "LOOP", "LYNN", "MAJJ",
"MOLC", "MULLM", "NC", "OLIVK", "PARKD", "POL", "PTRHUS",
"RAMS", "REYMA", "ROBCM", "ROBINE", "SAMJN", "SHARMM", "SJ",
"SJN", "SKINT", "SLOP", "SORT", "SPOE", "TELED", "THAN",
"THEL", "TURH", "VALK"), class = "factor"), Sales.3 = structure(c(1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c("", "AHMEM",
"AOK", "BACC", "BLAFM", "CHAMBA", "COUPSI", "DILP", "FCH",
"KW", "LOOP", "MAJJ", "PTRHUS", "RAMS", "ROBCM", "SAMJN",
"SHARMM", "SJ", "TELED", "THAN", "VALK"), class = "factor")), row.names = c(NA,
10L), class = "data.frame")
Комментарии:
1. то, что вы хотите, не очень понятно. например, SP1 появляется в позиции 6 df2 $ sales1 и в позиции 3 и 4 df2 $ sales2. итак, когда вы указываете, где они отображаются в любом из столбцов, я бы предположил, что вы хотите, чтобы результаты для SP1 в столбце A были (3, 4, 6) . почему результат равен 3? также вы говорите, что хотите сгруппировать по типу и году … хорошо, но у вас нет столбца типа и года, поэтому неясно, чего вы пытаетесь достичь.
2. хм, вы хотите знать, в каких строках
df2
данной продажи появляется стажер?3. Обновлено с использованием текущих данных
4. Для чего
iType
используются ваши текущие данные? Игнорируется ли это в этом процессе? Используется ли это в «разбивке по типу и году»?5. @Ben Тип — это Отдел / секция, к которому он принадлежит. Итак, этот период для этих разделов написан этим человеком.
Ответ №1:
Я не уверен, что это то, что вы ищете, но подумал, что это может быть полезно. С вашим интересом к использованию group_by
звучит так, как будто вам может понадобиться tidyverse
подход.
Здесь нужно добавить номера строк, чтобы вы могли group_by
в каждой строке видеть, присутствует ли стажер с продавцом в одной строке.
Затем используйте pivot_longer
для перевода в длинный формат и удаления пустых строк.
При группировании по номеру строки вы можете добавить индикатор того, что эти люди появятся у продавца-стажера. Он проверяет, не содержится ли человек в ilist
.
Наконец, вы можете group_by
каждого продавца включить только в ilist
с filter
и сложить количество появлений (предполагается, что только один раз в строке исходных данных) и количество контактов стажера.
library(tidyverse)
df2 %>%
mutate(rn = row_number()) %>%
pivot_longer(cols = -rn) %>%
na_if("") %>%
na.omit %>%
group_by(rn) %>%
mutate(with_trainee = ifelse(any(!value %in% ilist), 1, 0)) %>%
group_by(value) %>%
filter(value %in% ilist) %>%
summarise(A = n(),
B = sum(with_trainee))
Вывод
value A B
<chr> <int> <dbl>
1 SP1 3 1
2 SP2 1 0
3 SP3 3 1
4 SP4 2 1
5 SP5 3 1
Редактировать 1: используя ваши «текущие данные» и группируя результаты по годам из iYear
и iType
, вы можете попробовать это:
library(tidyverse)
df2 %>%
mutate(rn = row_number(),
iYear = substr(iYear, 1, 4)) %>%
pivot_longer(cols = -c(rn, iYear, iType)) %>%
na_if("") %>%
na.omit %>%
group_by(rn, iYear, iType) %>%
mutate(with_trainee = ifelse(any(!value %in% ilist), 1, 0)) %>%
group_by(value, iYear, iType) %>%
filter(value %in% ilist) %>%
summarise(A = n(),
B = sum(with_trainee))
Редактирование 2: дополнительное подробное объяснение:
Номера строк ( rn
через row_number
) полезны в этом случае, так как вы хотите знать, присутствуют ли продавцы в одно и то же время (что подразумевает «в пределах одной строки»). Итак, если 2 продавца используют одно и то же rn
, они присутствовали в одно и то же время.
iYear
изменен всего на год. Он использует substr()
(substring) для взятия с 1-го по 4-й символ iYear
, который в формате даты XXXX-XX-XX является годом.
pivot_longer
(и его друг, pivot_wider
) действительно эффективны для преобразования из длинных <-> широких форматов данных. В tidyr
пакете pivot_longer
принимает все столбцы (кроме rn
, iYear
, и iType
) и помещает в два столбца ( name
и value
). value
теперь продавец содержится в одном столбце вместо нескольких столбцов, с которых он начинался.
na_if("")
приведет к тому, что пустые строки ""
станут NA
(отсутствующие данные). Последующие na.omit
действия удалят эти строки с NA
помощью then.
Функция group_by
with rn
гарантирует, что вы смотрите коллективно на тех продавцов, которые разделяют то же rn
самое . Я добавил iYear
и iType
, чтобы они также отображались в итоговых итоговых результатах. Затем with_trainee
создается новый столбец, в котором будет указано, является ли этот продавец стажером или нет (после group_by
использования any
, чтобы увидеть, есть ли в векторе «любая строка» в группе, разделяющая одно и то же rn
ilist
). Если есть, то кодируйте как 1, если нет, то кодируйте как 0.
Следующий group_by
— by value
(или продавец), используя filter
, поскольку вам нужны результаты только для тех, кто находится внутри ilist
. (Если вы хотите, чтобы все, включая отсутствующих стажеров, отсутствовали ilist
, вы могли бы исключить эту строку.)
Финал summarise
работает с group_by
— with n()
, показывая количество строк данных на value
(или на одного продавца), которое совпадает с количеством различных rn
значений, которые могут отображаться у продавца в целом. Это sum(with_trainee)
общее количество раз with_trainee
, когда значение было 1 для данного value
(или продавца).
Вывод
value iYear iType A B
<fct> <chr> <fct> <int> <dbl>
1 SJ 2020 CFN 3 1
Комментарии:
1. Я добавил некоторые текущие данные, если это поможет
2. Пожалуйста, смотрите отредактированный ответ. Это берет год из
iYear
и группирует по году иiType
. Это ближе к тому, что вам нужно?3. Похоже, это работает, и это потрясающе. Огромная помощь. Глядя на то, что вы создали, мне еще предстоит пройти много миль. Если я правильно это читаю, вы: Добавили идентификационные номера потока > Сделали iYear всего на год> (Pivot_longer Мне нужно будет исследовать, поскольку я с этим не сталкивался) > Не применимо, если пусто > (нет.опустить, мне нужно исследовать) > Группировать по трем типам (число,год и тип)> Добавьте дополнительный столбец для значений, которых нет в моем списке, чтобы идентифицировать стажера; присвоив им 1> Фильтр по тому, что есть в моем списке> Выведите данные с количеством совпадений в списке и добавьте стажеров, правильно ли я это делаю?
Ответ №2:
Честно говоря, я не совсем понимаю ожидаемый результат, поскольку вы говорите, что ожидаете SP2 | 1 | 0
, но SP2 не появился в строке 1. следующее может делать то, что вы хотите … или нет.
library(data.table)
sales <- data.table(sale = c("SP1", "SP2", "SP3", "SP4", "SP5"))
sales_group <-
data.table(
sales1 = c("SP5", "SP5", "SP4", "SP3", "SP2", "SP1", "SP3"),
sales2 = c("", "SP4", "SP1", "SP1", "SP5", "SP3", ""),
sales3 = c("", "SP9", "", "SP6", "", "", "")
)
all <- sort(sales_group[, unique(c(sales1, sales2, sales3))])
all <- all[all != ""]
trainees <- all[!all %in% c(sales$sale, "")]
sales_group[, pos := seq(.N)]
sales1 <- merge(sales, sales_group, by.x = "sale", by.y = "sales1")
sales2 <- merge(sales, sales_group, by.x = "sale", by.y = "sales2")
sales3 <- merge(sales, sales_group, by.x = "sale", by.y = "sales3")
setnames(sales1, c("sale", "plusone", "plustwo", "sales_pos"))
setnames(sales2, c("sale", "plusone", "plustwo", "sales_pos"))
setnames(sales3, c("sale", "plusone", "plustwo", "sales_pos"))
sales_visit_by_sale <- rbind(sales1, sales2, sales3)
sales_visit_by_sale[, with_trainee := FALSE]
sales_visit_by_sale[(plusone %in% trainees) | (plustwo %in% trainees), with_trainee := TRUE]
sales_visit_by_sale[(order(sale, sales_pos)), .(sale, sales_pos, with_trainee)]
Комментарии:
1. Я добавил некоторые текущие данные, если это поможет