在 R 中循环变量和数据帧

Looping over variables and data frames in R

提问人:Struggle on 提问时间:11/14/2023 更新时间:11/14/2023 访问量:70

问:

我有一个数据争论的问题,我真的无法理解。我遇到过数据粘在一长串中,其中包括几个人的姓名和性别。我想从这些字符串中挑选出特定的信息片段,并将它们放在一个数据框中。我已经设法做到了这一点,但我的解决方案远非优雅,如果可以遍历变量和数据帧而不是使用我笨重的解决方案,那就太好了。我无法共享原始数据,但我创建了一个示例数据。数据遵循以下结构:

df <- data.frame(Movie=c("Matrix", "Black Widow"), 
                 People=c("¤¤¤34543¤Keanu Reeves¤932 9273¤Male¤¤¤02734¤Laurence Fishburne¤936 2740¤Male¤¤¤47622¤Carrie-Anne Moss¤938 0722¤Female¤¤¤21539¤Hugo Weaving¤953 6124¤Male",
                 "¤¤¤98237¤Scarlett Johansson¤923 8734¤Female¤¤¤72367¤Florence Pugh¤732 4284¤Female¤¤¤55661¤David Harbour¤981 2469¤Male"))

最后,我想到达以下数据框:

#        Movie               Name    Sex
#1      Matrix       Keanu Reeves   Male
#2 Black Widow Scarlett Johansson Female
#3      Matrix Laurence Fishburne   Male
#4 Black Widow      Florence Pugh Female
#5      Matrix   Carrie-Anne Moss Female
#6 Black Widow      David Harbour   Male
#7      Matrix       Hugo Weaving   Male

好的,这是我的解决方案:

我首先计算分隔字符的出现次数,然后将数据分成几部分:

library(stringr)
df$people_count <- str_count(df$People, "¤")

max_people_count <- max(df$people_count)

new_varnames <- paste0("Name", 0:max_people_count)
df[c(new_varnames)] <- str_split_fixed(df$People, "¤", max_people_count+1)

我想选择第 1、8 和 10 列,并将第 8 列和第 10 列重命名为“姓名”和“性别”。然后我想从第 1 列和第 1 列开始,每 6 列从 8 列和 10 列开始选择一次。我的解决方案是创建新的数据框,重命名选定的列,最后将所有内容重新组合在一起:

col_select <- c(8, 10)

df1 <- df[ , c(1, col_select)]
colnames(df1)[2] ="Name"
colnames(df1)[3] ="Sex"



col_select <- col_select+6
df2 <- df[ , c(1, col_select)]
colnames(df2)[2] ="Name"
colnames(df2)[3] ="Sex"

col_select <- col_select+6
df3 <- df[ , c(1, col_select)]
colnames(df3)[2] ="Name"
colnames(df3)[3] ="Sex"

col_select <- col_select+6
df4 <- df[ , c(1, col_select)]
colnames(df4)[2] ="Name"
colnames(df4)[3] ="Sex"


final_df <- rbind(df1, df2, df3, df4)

final_df <- subset(final_df, Name != "")  # remove blank lines

正如你所看到的,我在 R 方面的技能是有限的。必须有一种方法可以在循环中做到这一点。我的问题是我无法在工作for循环中创建数据帧的名称。如果我能做到这一点,我就不必一遍又一遍地重复相同的行,只需更改数据框的名称(请注意,我的原始数据要大得多)。

我非常感谢这个问题的一些帮助,因为我正在努力学习如何以有效的方式使用 R。

R DataFrame for 循环

评论


答:

5赞 Allan Cameron 11/14/2023 #1

你不需要显式循环。

在基础 R 中,一旦我们找到了中间不需要的字符的模式,就可以使用将每个字符串的有用部分拆分为一个向量。然后,可以将每个向量转换为其中的数据帧。然后,可以将数据帧的结果从原始数据集中打印到相应的影片中。最后,可以使用以下命令将数据框的结果列表全部连接在一起strsplitlapplylistMapdo.call("rbind", ...)

do.call('rbind',
  Map(\(x, y) cbind(Movie = x, y), df$Movie, df$People |>
    strsplit('¤¤¤\\d+¤|¤\\d+ \\d+¤') |>
    lapply(\(x) as.data.frame(t(matrix(x[-1], nrow = 2))) |>
              setNames(c('Name', 'Sex'))))) |>
  `rownames<-`(NULL)
#>         Movie               Name    Sex
#> 1      Matrix       Keanu Reeves   Male
#> 2      Matrix Laurence Fishburne   Male
#> 3      Matrix   Carrie-Anne Moss Female
#> 4      Matrix       Hugo Weaving   Male
#> 5 Black Widow Scarlett Johansson Female
#> 6 Black Widow      Florence Pugh Female
#> 7 Black Widow      David Harbour   Male

如您所见,这适用于您的示例数据框。然而,这种字符串解析高度依赖于确切的输入,因此尚不清楚这是否适用于您的实际数据。

评论

0赞 PesKchan 11/14/2023
stackoverflow.com/questions/77475525/......我会要求并要求您了解如何解决这个问题。
2赞 IRTFM 11/14/2023
@PesKchan 目前还不清楚你想象到与这个问题有什么联系。这是关于组内的键值配对。你的问题没有这些。艾伦提供了一个优雅的解决方案,尽管作为一个教学练习,它似乎有点简洁,我认为两者都是循环。Maplapply
0赞 PesKchan 11/14/2023
我实际上正在寻找艾伦的其他解决方案,但是在两者之间我切换了标签,我认为我遇到了类似的问题
0赞 Struggle on 11/14/2023
哇,我所需要的少量代码给我留下了深刻的印象。谢谢!该代码运行良好(在示例中),如果时间允许,我将尝试将其应用于我的原始数据(这是一个业余时间项目)。我不得不承认,关于代码的实际工作原理,我没有太多线索,所以我会尽量留出时间来正确破译它。我来自Stata环境。我年轻时学会了用 Stata 编程,现在,我长大了,试图过渡到 R。当我年轻的时候,我绝对是一个学得更快的人:-)。非常感谢您的帮助!