【发布时间】:2018-07-17 10:50:38
【问题描述】:
我对这个问题有点头疼。 我在 Excel 中有一个通过从网站复制粘贴生成的表格,其中每一行代表一个样本。在这一行中有一个特定的字段,其中包含可变数量的单元格。 我附上一张截图,以便您可以轻松理解我的意思:
现在,我想做的是将这些字段中的每一个都放在一个单独的列中。如果这是固定数量的行,我会简单地通过“粘贴特殊”进行转置,然后在固定数量的字段处断开结果行,以便让所有内容都井井有条。 但是,每行的字段数会发生变化;并非所有样本都具有相同数量的属性,这意味着转置整个列是不够的。我现在一直在做几分钟的事情是转置所有内容并手动移动单元格,以便在没有价值的地方出现空白,但每一行的属性数量保持不变:
但是,这很乏味、耗时,而且由于我有 500 多个条目,这将需要很长时间。
我一点也不精通 excel 脚本,但我对在基础 R 中的争论有一定的了解。我必须解决的主要问题是,如果我在 R 中将此表作为文本文件导入,则每个单元格在该列中将单独分配一行,使折叠非常复杂。
这是我目前想出的:
#This is the data I need to wrangle
tmp <- read.delim("pdata.txt", header = T, stringsAsFactors = F)
> head(tmp)
Title Source.name Disease.state Sex Age
1 LT000842RU_CTRL Flash frozen whole lung Control 1-Male 75
2 NA
3 NA
4 NA
5 LT001600RL_ILD Flash frozen whole lung Interstitial lung disease 1-Male 54
6 NA
Gold.stage Characteristics Ild.subtype Pneumocystis.colonization
1 0-At Risk smoker?: 2-Ever (>100)
2 %predicted fev1 (pre-bd): 96
3 %predicted fvc (pre-bd): 97
4 %predicted dlco: 78
5 %emphysema (f-950): 1.903 2-UIP/IPF
6 smoker?: 2-Ever (>100)
如您所见,“Title”列中有空格,这是由于“Characteristics”列有更多相同标题的条目造成的。
#Extremely ugly series of gsub to make for compatible colnames (no spaces, no dashes, etc)
d = sapply(tmp[,7], function(x) {gsub(x, pattern = " ", replacement = "_", fixed = T)})
dd = sapply(d, function(x) {gsub(x, pattern = "%", replacement = "", fixed = T)})
dd = sapply(dd, function(x) {gsub(x, pattern = "_(f-950):_", replacement = " ", fixed = T)})
dd = sapply(dd, function(x) {gsub(x, pattern = "?:", replacement = "", fixed = T)})
dd = sapply(dd, function(x) {gsub(x, pattern = "smoker_", replacement = "smoker ", fixed = T)})
dd = sapply(dd, function(x) {gsub(x, pattern = ":_", replacement = " ", fixed = T)})
dd = sapply(dd, function(x) {gsub(x, pattern = "(", replacement = "", fixed = T)})
dd = sapply(dd, function(x) {gsub(x, pattern = ")", replacement = "", fixed = T)})
dd = sapply(dd, function(x) {gsub(x, pattern = "-", replacement = "_", fixed = T)})
#Use the character vector that has been gsubbed as the attributes column in the df
tmp[,7] = dd
#Take the rows that are not empty, i.e. those that have the name of the sample and will be the starting rows for the attributes
nonempty = which(tmp[,1] != "")
jumps = nonempty[2:length(nonempty)]-nonempty[1:length(nonempty)-1]
jumps = c(jumps, 0)
#Make dummy columns with the same names as the gsubbed attributes
tmp$emphysema = tmp[,1]
tmp$smoker = tmp[,1]
tmp$predicted_fcv_pre_bd = tmp[,1]
tmp$predicted_fev1_pre_bd = tmp[,1]
tmp$predicted_fev1_post_bd = tmp[,1]
tmp$predicted_fcv_post_bd = tmp[,1]
tmp$predicted_dlco = tmp[,1]
#This is a loop to fill in the columns with the values extracted from the gsubbed attributes column
for(i in 1:length(nonempty))
{
a = as.data.frame(tmp[seq(nonempty[i], (nonempty[i]+jumps[i]-1),by = 1),7])
chars = colnames(tmp[,10:ncol(tmp)])
for (j in chars)
{
gg = as.character(a[grep(pattern = j, x = a[,1]),1])
if(length(gg) != 0) tmp[nonempty[i],j] = as.character(unlist(strsplit(gg, split = " "))[2]) else tmp[nonempty[i],j] = NA
}
}
# Make the new df by only taking the rows with samples
tmp2 = tmp[nonempty,]
#This is the resulting data frame:
> head(tmp2)
Title Source.name
LT000216LL_ILD LT000216LL_ILD Flash frozen whole lung
LT000379LU_ILD LT000379LU_ILD Flash frozen whole lung
LT000842RU_CTRL LT000842RU_CTRL Flash frozen whole lung
LT001600RL_ILD LT001600RL_ILD Flash frozen whole lung
LT001796RU_CTRL LT001796RU_CTRL Flash frozen whole lung
LT002410RM_ILD LT002410RM_ILD Flash frozen whole lung
Disease.state Sex Age Gold.stage
LT000216LL_ILD Interstitial lung disease 2-Female 70
LT000379LU_ILD Interstitial lung disease 1-Male 63
LT000842RU_CTRL Control 1-Male 75 0-At Risk
LT001600RL_ILD Interstitial lung disease 1-Male 54
LT001796RU_CTRL Control 1-Male 48 0-At Risk
LT002410RM_ILD Interstitial lung disease 1-Male 52
Characteristics Ild.subtype
LT000216LL_ILD emphysema 0.051 2-UIP/IPF
LT000379LU_ILD smoker 2_Ever_>100 9-Hypersensitive Pneumonitis (HP)
LT000842RU_CTRL smoker 2_Ever_>100
LT001600RL_ILD emphysema 1.903 2-UIP/IPF
LT001796RU_CTRL smoker 2_Ever_>100
LT002410RM_ILD emphysema 0.03 2-UIP/IPF
Pneumocystis.colonization emphysema smoker
LT000216LL_ILD 0.051 3_Never
LT000379LU_ILD <NA> 2_Ever_>100
LT000842RU_CTRL <NA> 2_Ever_>100
LT001600RL_ILD 1.903 2_Ever_>100
LT001796RU_CTRL <NA> 2_Ever_>100
LT002410RM_ILD 0.03 2_Ever_>100
predicted_fcv_pre_bd predicted_fev1_pre_bd
LT000216LL_ILD <NA> 56
LT000379LU_ILD <NA> 67
LT000842RU_CTRL <NA> 96
LT001600RL_ILD <NA> 40
LT001796RU_CTRL <NA> 107
LT002410RM_ILD <NA> 56
predicted_fev1_post_bd predicted_fcv_post_bd predicted_dlco
LT000216LL_ILD <NA> <NA> 36
LT000379LU_ILD <NA> <NA> 42
LT000842RU_CTRL <NA> <NA> 78
LT001600RL_ILD <NA> <NA> 16
LT001796RU_CTRL 110 <NA> 107
LT002410RM_ILD 60 <NA> 63
虽然我对这个结果相当满意,但我花了一些时间来做饭,而且它非常不灵活(非常适合这个特定的数据集),所以我想知道以下几点:
- 在 Excel 中是否有针对这种情况的快速修复?
- 或者,或者实际上更好:是否有基础/tidyverse 在 R 中以一种不像 我想出了一个?
提前致谢!
【问题讨论】:
-
对于 Excel 解决方案,我会先设置与表的数据连接,这样您就可以将数据导入 Excel,而不是复制/粘贴。根据结果,我将使用 Power Query 或 VBA 根据需要重新排列数据。可以分享一下网址吗?
-
感谢您的评论@RonRosenfeld。这是表格的来源:link(参见“示例”框架)。