如何计算列中的值并将它们与特定行匹配?
How do I count values in a column and match them with a specific row?
我有这样的数据集,其中 ID 和电子邮件对应于一个唯一的人。其余列代表以 person/row 命名的人。例如,ID 为 1 且电子邮件地址为 alex@gmail.com 的人在被问及问题时姓名为 Pete、Jane 和 Tim。
id email john_b alex_a pete jane tim
1 alex@gmail.com NA NA 1 1 1
2 pete@yahoo.com NA 1 1 NA NA
3 jane@q.com NA NA 1 NA 1
4 bea@mail.co NA 1 1 NA NA
5 tim@q.com NA NA 1 NA 1
我需要新的数据集看起来像这样,其中新的列提名表示 person/row 在数据集的其余部分中被命名的次数。例如,Pete 被 5 个人命名,并在提名列中获得 5,在具有相关电子邮件地址的行中。 Jane 曾被提名一次(由 alex@gmail.com),并在提名栏中获得 1,在 Jane 的电子邮件地址所在的行。
id email john_b alex_a pete jane tim nomination
1 alex@gmail.com NA NA 1 1 1 0
2 pete@yahoo.com NA 1 1 NA NA 5
3 jane@q.com NA NA 1 NA 1 1
4 bea@mail.co NA 1 1 NA NA 0
5 tim@q.com NA NA 1 NA 1 3
我觉得我需要 case-when 和 grepl 的组合,但我无法理解它。
感谢您的帮助!
如果您按照与电子邮件列相同的顺序组织您的姓名列,那么您可以简单地:
nomination <- colSums(df[, -(1:2)], na.rm = TRUE)
names(nomination) <- NULL
df <- cbind(df, nomination)
您好,我终于想出了一个代码,希望能让您达到您的期望。但是,我想不出任何方法来匹配 bea@mail.co
和 john_b
。这肯定需要比我聪明得多的头脑,但如果我能想到什么,我会在这里更新我的代码:
library(dplyr)
library(tidyr)
library(stringr)
df <- tribble(
~email, ~john_b, ~alex_a, ~pete, ~jane, ~tim,
"alex@gmail.com", NA, NA, 1, 1, 1,
"pete@yahoo.com", NA , 1, 1, NA, NA,
"jane@q.com", NA , NA, 1, NA, 1,
"bea@mail.co", NA, 1, 1, NA, NA,
"tim@q.com", NA , NA, 1, NA, 1
)
# First we count the number of times each person is named
nm <- df %>%
summarise(across(john_b:tim, ~ sum(.x, na.rm = TRUE))) %>%
pivot_longer(everything(), names_to = "names", values_to = "nominations")
nm
# A tibble: 5 x 2
names nominations
<chr> <dbl>
1 john_b 0
2 alex_a 2
3 pete 5
4 jane 1
5 tim 3
然后我们尝试将每个名字与其对应的电子邮件进行部分匹配。正如我之前提到的,这里唯一的问题是 john_b
。
nm2 <- nm %>%
rowwise() %>%
mutate(emails = map(names, ~ df$email[str_detect(df$email, str_sub(.x, 1L, 4L))])) %>%
unnest(cols = c(emails))
nm2
# A tibble: 4 x 3
names nominations emails
<chr> <dbl> <chr>
1 alex_a 2 alex@gmail.com
2 pete 5 pete@yahoo.com
3 jane 1 jane@q.com
4 tim 3 tim@q.com
最后我们通过emails
加入这两个数据帧:
df %>%
full_join(nm2, by = c("email" = "emails"))
# A tibble: 5 x 8
email john_b alex_a pete jane tim names nominations
<chr> <lgl> <dbl> <dbl> <dbl> <dbl> <chr> <dbl>
1 alex@gmail.com NA NA 1 1 1 alex_a 2
2 pete@yahoo.com NA 1 1 NA NA pete 5
3 jane@q.com NA NA 1 NA 1 jane 1
4 bea@mail.co NA 1 1 NA NA NA NA
5 tim@q.com NA NA 1 NA 1 tim 3
您也可以根据需要省略 names
列。我只是留下它们,以便您可以将它们放在一起比较。如果您可以对 john 的电子邮件进行一些修改,他们将完全匹配。
我有这样的数据集,其中 ID 和电子邮件对应于一个唯一的人。其余列代表以 person/row 命名的人。例如,ID 为 1 且电子邮件地址为 alex@gmail.com 的人在被问及问题时姓名为 Pete、Jane 和 Tim。
id email john_b alex_a pete jane tim
1 alex@gmail.com NA NA 1 1 1
2 pete@yahoo.com NA 1 1 NA NA
3 jane@q.com NA NA 1 NA 1
4 bea@mail.co NA 1 1 NA NA
5 tim@q.com NA NA 1 NA 1
我需要新的数据集看起来像这样,其中新的列提名表示 person/row 在数据集的其余部分中被命名的次数。例如,Pete 被 5 个人命名,并在提名列中获得 5,在具有相关电子邮件地址的行中。 Jane 曾被提名一次(由 alex@gmail.com),并在提名栏中获得 1,在 Jane 的电子邮件地址所在的行。
id email john_b alex_a pete jane tim nomination
1 alex@gmail.com NA NA 1 1 1 0
2 pete@yahoo.com NA 1 1 NA NA 5
3 jane@q.com NA NA 1 NA 1 1
4 bea@mail.co NA 1 1 NA NA 0
5 tim@q.com NA NA 1 NA 1 3
我觉得我需要 case-when 和 grepl 的组合,但我无法理解它。
感谢您的帮助!
如果您按照与电子邮件列相同的顺序组织您的姓名列,那么您可以简单地:
nomination <- colSums(df[, -(1:2)], na.rm = TRUE)
names(nomination) <- NULL
df <- cbind(df, nomination)
您好,我终于想出了一个代码,希望能让您达到您的期望。但是,我想不出任何方法来匹配 bea@mail.co
和 john_b
。这肯定需要比我聪明得多的头脑,但如果我能想到什么,我会在这里更新我的代码:
library(dplyr)
library(tidyr)
library(stringr)
df <- tribble(
~email, ~john_b, ~alex_a, ~pete, ~jane, ~tim,
"alex@gmail.com", NA, NA, 1, 1, 1,
"pete@yahoo.com", NA , 1, 1, NA, NA,
"jane@q.com", NA , NA, 1, NA, 1,
"bea@mail.co", NA, 1, 1, NA, NA,
"tim@q.com", NA , NA, 1, NA, 1
)
# First we count the number of times each person is named
nm <- df %>%
summarise(across(john_b:tim, ~ sum(.x, na.rm = TRUE))) %>%
pivot_longer(everything(), names_to = "names", values_to = "nominations")
nm
# A tibble: 5 x 2
names nominations
<chr> <dbl>
1 john_b 0
2 alex_a 2
3 pete 5
4 jane 1
5 tim 3
然后我们尝试将每个名字与其对应的电子邮件进行部分匹配。正如我之前提到的,这里唯一的问题是 john_b
。
nm2 <- nm %>%
rowwise() %>%
mutate(emails = map(names, ~ df$email[str_detect(df$email, str_sub(.x, 1L, 4L))])) %>%
unnest(cols = c(emails))
nm2
# A tibble: 4 x 3
names nominations emails
<chr> <dbl> <chr>
1 alex_a 2 alex@gmail.com
2 pete 5 pete@yahoo.com
3 jane 1 jane@q.com
4 tim 3 tim@q.com
最后我们通过emails
加入这两个数据帧:
df %>%
full_join(nm2, by = c("email" = "emails"))
# A tibble: 5 x 8
email john_b alex_a pete jane tim names nominations
<chr> <lgl> <dbl> <dbl> <dbl> <dbl> <chr> <dbl>
1 alex@gmail.com NA NA 1 1 1 alex_a 2
2 pete@yahoo.com NA 1 1 NA NA pete 5
3 jane@q.com NA NA 1 NA 1 jane 1
4 bea@mail.co NA 1 1 NA NA NA NA
5 tim@q.com NA NA 1 NA 1 tim 3
您也可以根据需要省略 names
列。我只是留下它们,以便您可以将它们放在一起比较。如果您可以对 john 的电子邮件进行一些修改,他们将完全匹配。