在 R 中循环变量和数据帧

Str*_* on 2 for-loop r dataframe

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

\n
df <- data.frame(Movie=c("Matrix", "Black Widow"), \n                 People=c("\xc2\xa4\xc2\xa4\xc2\xa434543\xc2\xa4Keanu Reeves\xc2\xa4932 9273\xc2\xa4Male\xc2\xa4\xc2\xa4\xc2\xa402734\xc2\xa4Laurence Fishburne\xc2\xa4936 2740\xc2\xa4Male\xc2\xa4\xc2\xa4\xc2\xa447622\xc2\xa4Carrie-Anne Moss\xc2\xa4938 0722\xc2\xa4Female\xc2\xa4\xc2\xa4\xc2\xa421539\xc2\xa4Hugo Weaving\xc2\xa4953 6124\xc2\xa4Male",\n                 "\xc2\xa4\xc2\xa4\xc2\xa498237\xc2\xa4Scarlett Johansson\xc2\xa4923 8734\xc2\xa4Female\xc2\xa4\xc2\xa4\xc2\xa472367\xc2\xa4Florence Pugh\xc2\xa4732 4284\xc2\xa4Female\xc2\xa4\xc2\xa4\xc2\xa455661\xc2\xa4David Harbour\xc2\xa4981 2469\xc2\xa4Male"))\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
#        Movie               Name    Sex\n#1      Matrix       Keanu Reeves   Male\n#2 Black Widow Scarlett Johansson Female\n#3      Matrix Laurence Fishburne   Male\n#4 Black Widow      Florence Pugh Female\n#5      Matrix   Carrie-Anne Moss Female\n#6 Black Widow      David Harbour   Male\n#7      Matrix       Hugo Weaving   Male\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

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

\n
library(stringr)\ndf$people_count <- str_count(df$People, "\xc2\xa4")\n\nmax_people_count <- max(df$people_count)\n\nnew_varnames <- paste0("Name", 0:max_people_count)\ndf[c(new_varnames)] <- str_split_fixed(df$People, "\xc2\xa4", max_people_count+1)\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
col_select <- c(8, 10)\n\ndf1 <- df[ , c(1, col_select)]\ncolnames(df1)[2] ="Name"\ncolnames(df1)[3] ="Sex"\n\n\n\ncol_select <- col_select+6\ndf2 <- df[ , c(1, col_select)]\ncolnames(df2)[2] ="Name"\ncolnames(df2)[3] ="Sex"\n\ncol_select <- col_select+6\ndf3 <- df[ , c(1, col_select)]\ncolnames(df3)[2] ="Name"\ncolnames(df3)[3] ="Sex"\n\ncol_select <- col_select+6\ndf4 <- df[ , c(1, col_select)]\ncolnames(df4)[2] ="Name"\ncolnames(df4)[3] ="Sex"\n\n\nfinal_df <- rbind(df1, df2, df3, df4)\n\nfinal_df <- subset(final_df, Name != "")  # remove blank lines\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

我真的很感谢对这个问题的帮助,因为我正在努力学习如何有效地使用 R。

\n

All*_*ron 5

You don\'t need an explicit loop.

\n

In base R you can use strsplit to split the useful parts of each string into a vector once we have found the pattern of the unwanted characters in between. Each vector can then be converted to a data frame inside lapply. The resulting list of data frames can then be Mapped to the appropriate movie from your original data set. Finally, the resultant lists of data frames can all be joined together using do.call("rbind", ...)

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

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

\n