我的数据框看起来有点像以下内容。 A1U_sweet实际上是实际数据帧中的第19列,而C1U_sweet是实际数据帧中的第39列。有20列以A ##开头,20列以C ##开头。
A1U_sweet A2F_dip A3U_bbq C1U_sweet C2F_dip C3U_bbq
1 2 1 NA NA NA
NA NA NA 4 1 2
2 4 7 NA NA NA
我想制作组合A值和C值的其他列。生成的数据框将包含类似于B1U_sweet和B2F_dip的列。
A1U_sweet A2F_dip A3U_bbq C1U_sweet C2F_dip C3U_bbq B1U_sweet B2F_dip
1 2 1 NA NA NA 1 2
NA NA NA 4 1 2 4 1
2 4 7 NA NA NA 2 4
有人提议我尝试以下代码。前两行有效,但在实现其余部分之后,我收到一条错误消息。
types <- grep('^A([0-9]|[12][0-9])[A-Z]_[a-z]+', names(df)) ## Get all "A"
patterns
types <- substr(types, 2, Inf) ## Remove the "A"
for (tp in types) {
aa <- df[[paste0('A', tp)]] ## "A" column
cc <- df[[paste0('C', tp)]] ## "C" column
df[[paste0('B', tp)]] <- ifelse(is.na(aa), aa, cc)
}
这是错误消息:
Error in `[[<-.data.frame`(`*tmp*`, paste0("B", tp), value = logical(0)) :
replacement has 0 rows, data has 94
In addition: Warning message:
In is.na(aa) : is.na() applied to non-(list or vector) of type 'NULL'
数据确实有94列,但我不明白为什么可能会触发此错误。我很感激任何帮助使这个代码正常运行!
编辑:这是我到目前为止所做的。我必须进入并手动更改我想要组合的每组列的列名。一定有更好的方法!df$B1U_sweetnsour<-A1U_sweetnsour
df$B1U_sweetnsour[is.na(df$B1U_sweetnsour)]<- C1U_sweetnsour[is.na(A1U_sweetnsour)]
答案 0 :(得分:1)
考虑mapply
以元素方式比较 A 列和 C 列,并一次性分配所有 B 列。并使用与sub
不同的gsub
,sub
仅替换第一次出现,以防列标题中的其他地方出现A.
new_B_cols <- sub("A", "B", names(df)[grep("^A", names(df))])
replace_na <- function(aa, cc) {
aa[is.na(aa)] <- cc[is.na(aa)]
return(aa)
}
df[new_B_cols] <- mapply(replace_na, df[grep("^A", names(df))], df[grep("^C", names(df))])
df[order(names(df))]
# A1U_sweet A2F_dip A3U_bbq B1U_sweet B2F_dip B3U_bbq C1U_sweet C2F_dip C3U_bbq
# 1 1 2 1 1 2 1 NA NA NA
# 2 NA NA NA 4 1 2 4 1 2
# 3 2 4 7 2 4 7 NA NA NA
答案 1 :(得分:0)
尝试使用head(types)来查看您的类型对象是否具有您希望的信息。如果没有,向grep命令添加value = TRUE可能是您正在寻找的解决方案。
types <- grep('^A([0-9]|[12][0-9])[A-Z]_[a-z]+', names(df), value=TRUE)
types <- substr(types, 2, Inf) ## Remove the "A"
for (tp in types) {
aa <- df[[paste0('A', tp)]] ## "A" column
cc <- df[[paste0('C', tp)]] ## "C" column
df[[paste0('B', tp)]] <- ifelse(is.na(aa), aa, cc)
}
答案 2 :(得分:0)
任务本身并不困难或复杂,但由于数据的排列方式,它似乎是这样。当您看到传达多个信息的变量名称时,自问是否可以更简单地排列数据通常会很有帮助。这个简单的主张是流行的&#34; tidy&#34;的核心。在R中进行数据处理的方法虽然我并不是那些以“&#34; tidy&#34;”的名义所做的一切的粉丝,但这个核心主张是合理的,你违反它(因为你&# 39;在这里做得非常出色)只是冒着使你的分析比你需要的更困难的风险。
好的第一步是重新排列数据,以便数据不会以列名编码:
new MyModelviewModel()
这可能看起来很多工作,但它使数据更容易使用,而且不仅仅适用于此特定操作。
现在数据已经转换为理智的安排,实际任务非常简单:
df <- read.table(
text = "A1U_sweet A2F_dip A3U_bbq C1U_sweet C2F_dip C3U_bbq
1 2 1 NA NA NA
NA NA NA 4 1 2
2 4 7 NA NA NA",
header = TRUE)
library(tidyr)
df <- data.frame(id = 1:nrow(df), df)
dfl <- gather(df, key = "key", value = "value", -id)
dfl <- separate(dfl, key, into = c("key", "kind", "type"), sep = c(1, 4))
df2 <- spread(dfl, key, value)
df2
## id kind type A C
## 1 1 1U_ sweet 1 NA
## 2 1 2F_ dip 2 NA
## 3 1 3U_ bbq 1 NA
## 4 2 1U_ sweet NA 4
## 5 2 2F_ dip NA 1
## 6 2 3U_ bbq NA 2
## 7 3 1U_ sweet 2 NA
## 8 3 2F_ dip 4 NA
## 9 3 3U_ bbq 7 NA
我强烈建议您将数据保留在这种安排中,因为当数据以这种方式表示时,其他操作可能会非常容易。如果你必须把它放回去(例如,为了显示目的),你可以这样做:
df2 <- transform(df2, B = ifelse(is.na(A), C, A))
df2
## id kind type A C B
## 1 1 1U_ sweet 1 NA 1
## 2 1 2F_ dip 2 NA 2
## 3 1 3U_ bbq 1 NA 1
## 4 2 1U_ sweet NA 4 4
## 5 2 2F_ dip NA 1 1
## 6 2 3U_ bbq NA 2 2
## 7 3 1U_ sweet 2 NA 2
## 8 3 2F_ dip 4 NA 4
## 9 3 3U_ bbq 7 NA 7
虽然这种方法显然比某些替代方案更冗长,但它具有解决困难根本原因的优点,而不是显示如何混淆并避免次优初始选择的后果。