R语言实现Cascading mutate:为歌词数据填充角色信息
解决歌词数据框角色列的级联填充问题
我懂你碰到的麻烦了——用lag()只能搞定紧邻的那一行false,但连续一串false的话,后面的就没法继续填充了对吧?别发愁,这里有两个靠谱的解决方案,第一个用tidyr包的方法尤其简洁高效,推荐优先试试。
方法一:用tidyr::fill()(最省心的方案)
fill()就是专门用来处理这种向下/向上填充最近非缺失值的场景,完美匹配你的需求。步骤很简单:
- 先把
character列里的字符串"false"转成NA(因为fill()是针对缺失值工作的) - 调用
fill()向下填充最近的非NA值 - (如果需要的话)可以再把剩余的NA转回
"false",不过看你的需求应该不需要,毕竟我们要的是填充角色值
示例代码:
library(dplyr) library(tidyr) cleaned_lyrics <- lyrics %>% # 将字符串"false"转换为NA mutate(character = ifelse(character == "false", NA, character)) %>% # 向下填充character列的NA,使用上方最近的非NA值 fill(character, .direction = "down") %>% # 要是你的原始数据里character是逻辑型的false,把上面的ifelse换成:character = ifelse(!character, NA, character) as.data.frame()
拿你给的示例数据测试的话,处理后第3-7行的character都会被填充成[PRISONERS],第8行保持[PRISONER #1],完全符合你的预期。
方法二:用dplyr累积分组(不用额外加载包)
要是你不想加载tidyr,可以用dplyr的cumsum()创建分组标记,然后在每个分组里统一填充角色值:
library(dplyr) cleaned_lyrics <- lyrics %>% # 创建分组:每遇到非"false"的character,就开启一个新分组 mutate(group_id = cumsum(character != "false")) %>% # 每个分组内,把character替换成本组第一个有效的角色值 group_by(group_id) %>% mutate(character = first(character[character != "false"])) %>% ungroup() %>% select(-group_id) %>% # 删掉临时的分组列 as.data.frame()
这个方法的逻辑是把连续的false行和它上方的有效角色行归为同一个分组,然后用分组里的第一个有效角色值填满整个分组的character列,同样能实现级联填充的效果。
为啥你之前的代码没生效?
你之前用lag(character)只能取前一行的值,当第3行被填充后,第4行的lag(character)还是原来的false(因为第3行原本就是false,还没被后续的填充逻辑处理),所以只能替换第一行false,后面的就没法继续了。而上面的两种方法都是基于累积传递最近有效值的逻辑,所以能搞定连续多个false的情况。
内容的提问来源于stack exchange,提问作者nimz713
相关产品推荐
相关产品推荐

