提问人:Struggle on 提问时间:11/14/2023 更新时间:11/14/2023 访问量:70
在 R 中循环变量和数据帧
Looping over variables and data frames in R
问:
我有一个数据争论的问题,我真的无法理解。我遇到过数据粘在一长串中,其中包括几个人的姓名和性别。我想从这些字符串中挑选出特定的信息片段,并将它们放在一个数据框中。我已经设法做到了这一点,但我的解决方案远非优雅,如果可以遍历变量和数据帧而不是使用我笨重的解决方案,那就太好了。我无法共享原始数据,但我创建了一个示例数据。数据遵循以下结构:
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 中,一旦我们找到了中间不需要的字符的模式,就可以使用将每个字符串的有用部分拆分为一个向量。然后,可以将每个向量转换为其中的数据帧。然后,可以将数据帧的结果从原始数据集中打印到相应的影片中。最后,可以使用以下命令将数据框的结果列表全部连接在一起strsplit
lapply
list
Map
do.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
如您所见,这适用于您的示例数据框。然而,这种字符串解析高度依赖于确切的输入,因此尚不清楚这是否适用于您的实际数据。
评论
Map
lapply
评论