我的数据框如下:
product<-c("ab","ab","ab","ac","ac","ac")
shop<-c("sad","sad","sad","sadas","fghj","xzzv")
category<-c("a","a","a","c","b","b")
tempr<-c(35,35,14,24,14,5)
value<-c(0,0,-6,8,4,0)
store<-data.frame(product,shop,category,tempr,value)
product shop category tempr value
1 ab sad a 35 0
2 ab sad a 35 0
3 ab sad a 14 -6
4 ac sadas c 24 8
5 ac fghj b 14 4
6 ac xzzv b 5 0
我想以某种方式转换此数据框,以便保留唯一的产品名称,并将商店名称从字段值转换为列名(反之亦然)。我想用tempr
及其相对的value
的组合来填充此数据帧,但仅适用于不为0的值,否则单元格应该为空。但是,正如您所注意到的,我的记录具有相同的product
和shop
,但是具有不同的温度和数值(绝对)。问题在于它们彼此覆盖。在这种情况下(名称相同,商店相同但tmpr
-value
不同)应以非零的情况为准。例如,应该显示170(62)而不是170(0)(如果两者都存在)。如果商店中不存在某种产品,则单元格也应该为空。最终形式的一个示例是:
store2
product sad sadas fghj xzzv
1 ab 14(-6)
2 ac 24(8) 14(4)
第一种可能的方法:
store2 <- matrix(NA,ncol=length(unique(store$shop)),nrow=length(unique(store$product)))
colnames(store2) <- unique(store$shop)
rownames(store2) <- unique(store$product)
for(i in 1:ncol(store)) {
store2[store[i,'product'],store[i,'shop']] <- paste0(store[i,c('tempr')],'(',store[i,'value'],')')
}
第二种可能的方法:
library(tidyverse)
store %>%
mutate(shop = factor(shop, levels = unique(shop))) %>%
filter(value != 0) %>%
mutate(val = sprintf("%s(%s)", tempr, value)) %>%
select(product, shop, val) %>%
group_by(product) %>%
complete(shop) %>%
spread(shop, val)
除了这个结果之外,我还希望能够以相同的逻辑使用category
。下图显示了我希望使用相同填充逻辑的所有可能组合。
答案 0 :(得分:3)
不确定我是否完全理解这个问题,但是下面的代码会生成您的示例数据框。
library(tidyverse)
product<-c("ab","ab","ab","ac","ac","ac")
shop<-c("sad","sad","sad","sadas","fghj","xzzv")
category<-c("a","a","a","c","b","b")
tempr<-c(35,35,14,24,14,5)
value<-c(0,0,-6,8,4,0)
store<-data.frame(product,shop,category,tempr,value)
store %>% filter(value != 0 ) %>% # Remove 0 values
mutate(combined = paste0(tempr,"(",value,")")) %>% # Combine columns for spread
select(-tempr,-value) %>% #
spread(shop,combined) # spread to create shop columns and temr/value values.
# product category fghj sad sadas
# 1 ab a <NA> 14(-6) <NA>
# 2 ac b 14(4) <NA> <NA>
# 3 ac c <NA> <NA> 24(8)
答案 1 :(得分:1)
store$shop<-factor(store$shop,levels=c("sad","sadas","fghj","xzzv"))
#to avoid the change of column sequence of final outcome
store$tv<-ifelse(store$value==0,"",paste(store$tempr,"(",store$value,")",sep=""))
cast(store[,c(-3,-4,-5)],product~shop,function(x) paste(x,sep="",collapse=""), value="tv")
#due to one colname of the original store dataset is "value", firstly masked
#the original "value" column,otherwise, it automatically used as value-fill
# column
product sad sadas fghj xzzv ab 14(-6) ac 24(8) 14(4)"