【问题标题】:Merging dataframe cells based on content根据内容合并数据框单元格
【发布时间】:2021-02-02 20:24:13
【问题描述】:

我继承了一个丑陋的数据框,如下所示:

data.bad <- data.frame(
'NameId' = c('350-8D6A','BC2-85E2','426-C0FA','615-8E09','651-8D6F','DE8-3D0F','2B6-D039','5E9-EE00','38F-75E4','B02-FBBC','B7A-821E','95A-B349','A8C-4A7B','3F6-90A1'),
'Tribe' = c('Heliantheae','Heliantheae','Cichorieae','Cichorieae','Cichorieae','Senecioneae','Vernonieae','Tageteae','Vernonieae','Vernonieae','Millerieae','Inuleae','Astereae','Cardueae'),
'NameFull' = c('Wedelia mexicana (Sch.Bip.) McVaugh','Wedelia modesta Baker','Youngia multiflora (Thunb.) DC.','Youngia napifera DC. ex Wight','Scorzonera mucida Rech.f. Aellen & Esfand.','Senecio hualtaranensis Petenatti Ariza & Del Vitto','Baccharoides tolypophora (Mattf.) Isawumi El-Ghazaly & B.Nord.','Bajacalia crassifolia (S.Watson) Loockerman B.L.Turner & R.K.Jansen','Vernonia westermanii Ekman & Dusen','Vernonia westiniana Less.','Oteiza scandens Panero Villaseeor & Medina','Pulicaria hesperia Maire Weiller & Wilczek','Aster chusanensis Y.S.Lim','Cheirolophus mansanetianus Stubing'),
'Status' = c('Accepted','Accepted','Synonym','Synonym','Accepted','Accepted','Synonym','Synonym','Unknown','Unknown','Unknown','Unknown','Hyun','J.B.Peris'),
'AcceptedName' = c('Wedelia mexicana (Sch.Bip.) McVaugh','Wedelia modesta Baker','Youngia japonica (L.) DC.','Youngia japonica (L.) DC.','','','','','NULL','NULL','','','Y.D.Kim & H.C.Shin','Olivares & J.Marten')
)
  • 第 1 列:字母数字标识符 - 很好
  • 第 2 列:更高级别的分类,单一名称 - 精细
  • 第 3 列:表示物种名称和作者的可变长度字符串 - 有时缺少一些已拆分为第 4 列(有时为 5 列)的文本 - 看起来像是在某些时候留下了逗号分隔文本,但不再包含在数据中。
  • 第 4 列:名称作为单个词的有效性 - 应该为“已接受”、“同义词”或“NULL”,但在某些情况下为空,在最坏的情况下,文本应在第 3 列。
  • 第 5 列:接受的名称 - 应包含有效的二项式和作者(类似于第 3 列)。第 5 列的内容应为: 如果第 4 列 = “已接受”,则与第 3 列相同;如果“同义词”则不同;如果“未知”,则为“NULL”),但有时包含第 3 列的文本片段,有时为空(并且无法从此处的其他列推断)。

第 1-4、9、10 行是正确格式的示例。 第 13,14 行搞砸了,需要将第 4 列和第 5 列的内容合并到第 3 列(中间有逗号),新空的第 4 列和第 5 列用“FLAG”填充以向我表明他们需要注意。 第 5-8、11、12 行是第 5 列中的缺失数据,可以从第 4 列推断出来(“已接受”= 第 3 列的内容;“同义词”=“标志”(向我表明缺少数据);“未知" = "NULL")。

理想的结果是:

data.best <- data.frame(
  'NameId' = c('350-8D6A','BC2-85E2','426-C0FA','615-8E09','651-8D6F','DE8-3D0F','2B6-D039','5E9-EE00','38F-75E4','B02-FBBC','B7A-821E','95A-B349','A8C-4A7B','3F6-90A1'),
  'Tribe' = c('Heliantheae','Heliantheae','Cichorieae','Cichorieae','Cichorieae','Senecioneae','Vernonieae','Tageteae','Vernonieae','Vernonieae','Millerieae','Inuleae','Astereae','Cardueae'),
  'NameFull' = c('Wedelia mexicana (Sch.Bip.) McVaugh','Wedelia modesta Baker','Youngia multiflora (Thunb.) DC.','Youngia napifera DC. ex Wight','Scorzonera mucida Rech.f. Aellen & Esfand.','Senecio hualtaranensis Petenatti Ariza & Del Vitto','Baccharoides tolypophora (Mattf.) Isawumi El-Ghazaly & B.Nord.','Bajacalia crassifolia (S.Watson) Loockerman B.L.Turner & R.K.Jansen','Vernonia westermanii Ekman & Dusen','Vernonia westiniana Less.','Oteiza scandens Panero Villaseeor & Medina','Pulicaria hesperia Maire Weiller & Wilczek','Aster chusanensis Y.S.Lim, Hyun, Y.D.Kim & H.C.Shin','Cheirolophus mansanetianus Stubing, J.B.Peris, Olivares & J.Marten'),
  'Status' = c('Accepted','Accepted','Synonym','Synonym','Accepted','Accepted','Synonym','Synonym','Unknown','Unknown','Unknown','Unknown','FLAG','FLAG'),
  'AcceptedName' = c('Wedelia mexicana (Sch.Bip.) McVaugh','Wedelia modesta Baker','Youngia japonica (L.) DC.','Youngia japonica (L.) DC.','Scorzonera mucida Rech.f. Aellen & Esfand.','Senecio hualtaranensis Petenatti Ariza & Del Vitto','FLAG','FLAG','NULL','NULL','NULL','NULL','FLAG','FLAG')
)

这对我来说有太多的活动部件。我能找到的所有示例都是合并两个单独的数据帧,但不以现有数据帧中的元素为条件。

注意:仅将第 4 列和第 5 列中的错误文本合并回第 3 列的部分解决方案将是一个非常好的开始(如下),但显然会喜欢一个简洁的完整解决方案!

data.good <- data.frame(
  'NameId' = c('350-8D6A','BC2-85E2','426-C0FA','615-8E09','651-8D6F','DE8-3D0F','2B6-D039','5E9-EE00','38F-75E4','B02-FBBC','B7A-821E','95A-B349','A8C-4A7B','3F6-90A1'),
  'Tribe' = c('Heliantheae','Heliantheae','Cichorieae','Cichorieae','Cichorieae','Senecioneae','Vernonieae','Tageteae','Vernonieae','Vernonieae','Millerieae','Inuleae','Astereae','Cardueae'),
  'NameFull' = c('Wedelia mexicana (Sch.Bip.) McVaugh','Wedelia modesta Baker','Youngia multiflora (Thunb.) DC.','Youngia napifera DC. ex Wight','Scorzonera mucida Rech.f. Aellen & Esfand.','Senecio hualtaranensis Petenatti Ariza & Del Vitto','Baccharoides tolypophora (Mattf.) Isawumi El-Ghazaly & B.Nord.','Bajacalia crassifolia (S.Watson) Loockerman B.L.Turner & R.K.Jansen','Vernonia westermanii Ekman & Dusen','Vernonia westiniana Less.','Oteiza scandens Panero Villaseeor & Medina','Pulicaria hesperia Maire Weiller & Wilczek','Aster chusanensis Y.S.Lim, Hyun, Y.D.Kim & H.C.Shin','Cheirolophus mansanetianus Stubing, J.B.Peris, Olivares & J.Marten'),
  'Status' = c('Accepted','Accepted','Synonym','Synonym','Accepted','Accepted','Synonym','Synonym','Unknown','Unknown','Unknown','Unknown','',''),
  'AcceptedName' = c('Wedelia mexicana (Sch.Bip.) McVaugh','Wedelia modesta Baker','Youngia japonica (L.) DC.','Youngia japonica (L.) DC.','','','','','NULL','NULL','','','','')
)

希望这有点道理,很高兴澄清。 非常感谢任何帮助!

【问题讨论】:

  • 这里不需要任何合并,只需使用条件语句对 data.frame 进行基本操作。此外,在 data.best 的第 3 行和第 4 行,您没有将 AcceptedName 保留为“FLAG”,尽管它们处于“同义词”状态。对吗?
  • 嗨@CainãMaxCouto-Silva,嗯,好的。我想我会看那条路线,感谢您的帮助!没错。第 3 行和第 4 行区域已正确填充在原始损坏的数据框中 - 名称已记录为与“NameFull”列不同(同义词)。这是“状态”列是“同义词”但“接受名称”字段为空的地方,我需要一个标志,因为无法用给定数据推断这些单元格的内容:(

标签: r dataframe merge conditional-statements


【解决方案1】:

正如我所说,这个问题不需要合并。另外,我建议使用data.table 包来解决您的问题,因为根据条件在特定行执行修改会更简单。

使用data.table 的解决方案是:

# Load data.table
library(data.table)

# Set data.bad as data.table
setDT(data.bad)

# Define Valid Status
valid_status <- c("Accepted", "Synonym", "Unknown")

# Join invalid status to NameFull column
data.bad[!Status %in% valid_status, NameFull := paste(NameFull, Status, sep = ", ")]
# then flag invalid status
data.bad[!Status %in% valid_status, Status := "FLAG"]

# Join AcceptedName to NameFull if Status == FLAG (and Accepted Name is not NULL)
data.bad[Status == "FLAG" & AcceptedName != "NULL", NameFull := paste(NameFull, AcceptedName, sep = ", ")]

# Fix column 5
data.bad[Status == "Accepted", AcceptedName := NameFull]
data.bad[Status == "Synonym" & AcceptedName == "", AcceptedName := "FLAG"]
data.bad[Status == "Unknown", AcceptedName := "NULL"]
data.bad[Status == "FLAG" & !AcceptedName %in% c("FLAG", "NULL"), AcceptedName := "FLAG"]

# Now, data.bad is data.good
data.good <- copy(data.bad)

如果您想将数据设置回data.frame 类,只需输入setDF(data.good)

使用 R 基础:

# Define Valid Status
valid_status <- c("Accepted", "Synonym", "Unknown")

# Join invalid status to NameFull column
idx <- !data.bad$Status %in% valid_status # set invalid status indexes
data.bad$NameFull[idx] = paste(data.bad$NameFull[idx], data.bad$Status[idx], sep = ", ")
# then flag invalid status
data.bad$Status[idx] <- "FLAG"

# Join AcceptedName to NameFull if Status == FLAG (and Accepted Name is not NULL)
idx <- data.bad$Status == "FLAG" & data.bad$AcceptedName != "NULL"  # get indexes with status == "FLAG"
data.bad$NameFull[idx] <- paste(data.bad$NameFull[idx], data.bad$AcceptedName[idx], sep = ", ")

# Fix column 5
data.bad$AcceptedName[data.bad$Status == "Accepted"] <- data.bad$NameFull[data.bad$Status == "Accepted"]
data.bad$AcceptedName[data.bad$Status == "Synonym" & data.bad$AcceptedName == ""] <- "FLAG"
data.bad$AcceptedName[data.bad$Status == "Unknown"] <- "NULL"
data.bad$AcceptedName[data.bad$Status == "FLAG" & !data.bad$AcceptedName %in% c("FLAG", "NULL")] <- "FLAG"

【讨论】:

  • 太棒了!像魅力一样工作,并为我将来保证的未来损坏的数据框问题提供了一个很好的模板。谢谢!
猜你喜欢
  • 2017-10-14
  • 1970-01-01
  • 1970-01-01
  • 2017-03-16
  • 1970-01-01
  • 2021-11-01
  • 2014-06-07
  • 1970-01-01
  • 2018-12-25
相关资源
最近更新 更多