【问题标题】:How do I count values in a column and match them with a specific row?如何计算列中的值并将它们与特定行匹配?
【发布时间】:2021-06-27 15:55:44
【问题描述】:

我的数据集看起来像这样,其中 ID 和电子邮件对应于一个独特的人。其余列代表由该人/行命名的人。例如,当被问及问题时,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

我需要新的数据集看起来像这样,其中一个新的列提名表示该人/行在数据集的其余部分中被命名的次数。例如,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,但我无法理解它。

感谢您的帮助!

【问题讨论】:

  • 请将您的数据作为对象粘贴到dput(your_data) 的问题中;你试过什么代码?这将使那些可能想要帮助测试和验证解决方案的人生活得更轻松。
  • 我已经为您的问题发布了答案,如果您能检查一下,我会很高兴。
  • 亲爱的 Rakhim,您尝试过我朋友 akrun 建议的代码吗?

标签: r tidyverse tidyr case-when grepl


【解决方案1】:

如果您按照与电子邮件列相同的顺序组织您的姓名列,那么您可以简单地:

nomination <- colSums(df[, -(1:2)], na.rm = TRUE)
names(nomination) <- NULL
df <- cbind(df, nomination)

【讨论】:

  • 谢谢,史蒂夫。可以想象,以正确的顺序组织列和行很容易在处理大型数据集时失控。您是否看到了另一种解决方法?
【解决方案2】:

您好,我终于想出了一个代码,希望能达到您的预期。但是,我想不出任何将bea@mail.cojohn_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 的电子邮件进行一些修改,它们将完全匹配。

【讨论】:

  • @AnoushiravanR 也许df %&gt;% pivot_longer(cols = -email) %&gt;% group_by(name) %&gt;% summarise(nominations = sum(value, na.rm = TRUE), email = email[str_which(email, str_remove(first(name), "_\\w+$"))], .groups = 'drop') %&gt;% complete(email = unique(df$email)) %&gt;% left_join(df, .)
  • @AnoushiravanR 是的,这确实有助于技能的发展。但是,任何方法都有其优点和缺点。 SO中的缺点有时会是某人非常激进的行为,或者投反对票等。如果你不太关心这些,这将是一个很好的平台,因为你会得到即时响应,自然地提高速度,你可能会开始快速思考因为几分之一秒很重要。其他选择包括通过参加课程或开始项目进行常规学习。各有优缺点
  • @AnoushiravanR 很容易替换,你可以使用%&gt;% mutate(nominations = replace_na(nominations, 0))
  • @akrun 你是绝对正确的。自从我开始访问这里的那一刻起,我的学习率呈指数级增长,正如您正确提到的,速度因素使您尝试更快地思考以提出解决方案。非常感谢您抽出宝贵时间,与您交谈非常愉快,您是我最大的灵感来源之一。
  • @AnoushiravanR 如果没有直接匹配,那么fuzzyjoin或stringdist join可能更有用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-22
相关资源
最近更新 更多