【问题标题】:How to efficiently replace these imdb movie title IDs with the actual title based on a column match?如何根据列匹配有效地将这些 imdb 电影标题 ID 替换为实际标题?
【发布时间】:2020-05-10 17:26:05
【问题描述】:

我一直在使用他们发布的一些 IMDB 数据在 R 中工作,并且今天在这方面被困了很长时间。

primaryName     tconst                 primaryTitle                          knownForTitles
1          Aaron Lim  tt2317744            My Friend Bernard tt0268228,tt0891369,tt2317744,tt3709694
2      Aaron Woodley  tt3228088          Spark: A Space Tail tt0326065,tt1650535,tt4426464,tt3228088
3 Abdelkader Belhedi tt11069302       The Carthage Castaways         tt11698758,tt11069302,tt0485746

我正在努力想出一种将knownForTitles ID 与tconst 列中的ID 匹配的方法。匹配后,我想用primaryTitle 中的实际标题名称替换knownForTitles 中的ID,如下所示。

primaryName     tconst                 primaryTitle                          knownForTitles
1          Aaron Lim  tt2317744            My Friend Bernard Movie Title,Movie Title,Movie Title,Movie Title
2      Aaron Woodley  tt3228088          Spark: A Space Tail Movie Title,Movie Title,Movie Title,Movie Title
3 Abdelkader Belhedi tt11069302       The Carthage Castaways         Movie Title,Movie Title,Movie Title

我只能想到使用一堆 for 循环,这对于数千行可能非常低效。如果有人能指出我更好的方向,那就太棒了。

【问题讨论】:

  • 你能用dput()分享你的几行数据吗?

标签: r loops for-loop imdb


【解决方案1】:

代码是这样的。解释如下。

代码

df = data.frame(primaryName = c("Aaron Lim", "Aaron Woodley"), tconst = c("tt2317744", "tt3228088"), primaryTitle = c("My friend Ron", "Spark: Some Title"), knownForTitles = c("tt0268228,tt0891369,tt2317744,tt3709694", "tt0326065,tt1650535,tt4426464,tt3228088"))
df$tconst = as.character(df$tconst)
Names = df %>%  
  mutate(V2 = strsplit(as.character(knownForTitles), ",")) %>% 
  tidyr::unnest(V2) %>% 
  select(-knownForTitles) %>% 
  as.data.frame(.) 
Movies = df[,2:3]
Modi = left_join(Names, Movies, by = c("V2" = "tconst")) 
Modi$primaryTitle.y = as.character(Modi$primaryTitle.y)
Modi[is.na(Modi$primaryTitle.y), "primaryTitle.y"] = "Test"

Modi %>% 
  group_by(tconst) %>%  
  summarise(primNew = stringr::str_c(primaryTitle.y, collapse = ", ")) %>% 
  inner_join(df, .)

输出

    primaryName    tconst      primaryTitle                          knownForTitles
1     Aaron Lim tt2317744     My friend Ron tt0268228,tt0891369,tt2317744,tt3709694
2 Aaron Woodley tt3228088 Spark: Some Title tt0326065,tt1650535,tt4426464,tt3228088
                              primNew
1     Test, Test, My friend Ron, Test
2 Test, Test, Test, Spark: Some Title

解释

让我们定义一些玩具数据。

    df = data.frame(primaryName = c("Aaron Lim", "Aaron Woodley"), 
                    tconst = c("tt2317744", "tt3228088"), 
                    primaryTitle = c("My friend", "Spark"), 
                    knownForTitles = c("tt0268228,tt0891369,tt2317744,tt3709694", "tt0326065,tt1650535,tt4426464,tt3228088"))
    df$tconst = as.character(df$tconst)

然后你可以用tidyr的unnest函数把所有的列字符串拆分成行,像这样

Names = df %>%  
  mutate(V2 = strsplit(as.character(knownForTitles), ",")) %>% 
  tidyr::unnest(V2) %>% 
  select(-knownForTitles) %>% 
  as.data.frame(.) 

结果

> Names
    primaryName    tconst      primaryTitle        V2
1     Aaron Lim tt2317744     My friend Ron tt0268228
2     Aaron Lim tt2317744     My friend Ron tt0891369
3     Aaron Lim tt2317744     My friend Ron tt2317744
4     Aaron Lim tt2317744     My friend Ron tt3709694
5 Aaron Woodley tt3228088 Spark: Some Title tt0326065
6 Aaron Woodley tt3228088 Spark: Some Title tt1650535
7 Aaron Woodley tt3228088 Spark: Some Title tt4426464
8 Aaron Woodley tt3228088 Spark: Some Title tt3228088

然后你得到所有tconstants 的电影名称

Movies = df[,2:3]
Modi = left_join(Names, Movies, by = c("V2" = "tconst")) 

结果

    primaryName    tconst    primaryTitle.x        V2    primaryTitle.y
1     Aaron Lim tt2317744     My friend Ron tt0268228              <NA>
2     Aaron Lim tt2317744     My friend Ron tt0891369              <NA>
3     Aaron Lim tt2317744     My friend Ron tt2317744     My friend Ron
4     Aaron Lim tt2317744     My friend Ron tt3709694              <NA>
5 Aaron Woodley tt3228088 Spark: Some Title tt0326065              <NA>
6 Aaron Woodley tt3228088 Spark: Some Title tt1650535              <NA>
7 Aaron Woodley tt3228088 Spark: Some Title tt4426464              <NA>
8 Aaron Woodley tt3228088 Spark: Some Title tt3228088 Spark: Some Title

由于这是玩具数据,有 NA 值会造成一些麻烦,所以我们这样做

Modi$primaryTitle.y = as.character(Modi$primaryTitle.y)
Modi[is.na(Modi$primaryTitle.y), "primaryTitle.y"] = "Test"

来应对。

最后,你修改匹配的电影并用

将它们折叠成一行
Modi %>% 
  group_by(tconst) %>%  
  summarise(primNew = stringr::str_c(primaryTitle.y, collapse = ", ")) %>% 
  inner_join(df, .)

结果

    primaryName    tconst      primaryTitle                          knownForTitles
1     Aaron Lim tt2317744     My friend Ron tt0268228,tt0891369,tt2317744,tt3709694
2 Aaron Woodley tt3228088 Spark: Some Title tt0326065,tt1650535,tt4426464,tt3228088
                              primNew
1     Test, Test, My friend Ron, Test
2 Test, Test, Test, Spark: Some Title

【讨论】:

    【解决方案2】:

    我们可以得到separate_rowsmatchknownForTitles中的数据,tconst得到对应的primaryTitle值,将每个Name的数据折叠在一起。

    library(dplyr)
    
    df %>%
      tidyr::separate_rows(knownForTitles, sep = ',') %>%
      mutate(knownForTitles = primaryTitle[match(knownForTitles, tconst)]) %>%
      group_by(primaryName) %>%
      summarise(knownForTitles = toString(na.omit(knownForTitles)))
    

    在base R中,我们可以拆分字符串和match

    df$knownForTitles <- sapply(strsplit(df$knownForTitles, ','), function(x) 
                     with(df, toString(na.omit(primaryTitle[match(x, tconst)]))))
    

    【讨论】:

    • Ronak,很抱歉我来晚了。我相信在您的dplyr 解释的最后一步中出现了问题?我得到一个带有 1 行 1 obs 的 df,所有字符串都在一个
    • @moolz 是的,我认为那是因为您已经加载了plyrdplyr,因此它正在询问函数summarise。您能否重新启动 R 并仅加载 dplyr 并检查上述内容或在最后一行使用 dplyr::summarise(knownForTitles = toString(na.omit(knownForTitles)))
    猜你喜欢
    • 2013-04-12
    • 1970-01-01
    • 2014-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-16
    • 1970-01-01
    • 2020-03-18
    相关资源
    最近更新 更多