在R中把不规则数据转化为可用的格式

问题描述 投票:3回答:1

假设我在一家公司工作,该公司向其客户提供多种不同的服务。我得到了一份关于所提供服务的数据报告,我需要进行分析。报告的格式是便于阅读和打印的,但不适合数据分析。

报告的格式如下。

输入:

customer <- c(1,2,2,3,3,3)
service1 <- c(1,3,5,1,3,5)
fee1 <- c(100,290,500,100,300,500)
service2 <- c("",4,"",2,4,8)
fee2 <- c("",400,"",200,390,800)

require(data.table)
DT <- data.table(customer, service1, fee1, service2, fee2)

打印到哪里?

> DT
   customer service1 fee1 service2 fee2
1:        1        1  100              
2:        2        3  290        4  400
3:        2        5  500              
4:        3        1  100        2  200
5:        3        3  300        4  390
6:        3        5  500        8  800

有很多客户,对于每个客户都有一些他们所消费的服务和相应的费用。服务和费用分四栏横向打印,然后溢出到新的一行。每个客户可以有任意数量的服务,但每个客户的每项服务只能发生一次,而且每个客户的服务费可以不同。它们可能总是以相同的顺序打印,尽管解决方案不应依赖这一点。

任务是将数据转化为可用的格式。我认为有两种不同的方法可以做到这一点。

第一种方案(长格式):切掉最后两列,为每个costumer创建一个新行,然后填入内容。

方案一是这样的。

    customer service fee
 1:        1       1 100
 2:        2       3 290
 3:        2       4 400
 4:        2       5 500
 5:        3       1 100
 6:        3       2 200
 7:        3       3 300
 8:        3       4 390
 9:        3       5 500
10:        3       8 800

第二种方案(宽格式):切掉除第一行以外的所有行,为被切掉的服务创建新的列,然后将服务标签转化为列头(并确保所有内容都在正确的位置)。

方案二是这样的。

   customer service.1 service.2 service.3 service.4 service.5 service.6 service.7 service.8
1:        1       100                                                                      
2:        2                           290       400       500                              
3:        3                 200       300       390       500                           800

我可以使用任何一种格式(在长和宽之间的转换相当容易)。

作为起点,我想我必须找到每个客户的服务数量(方案一)或唯一服务的数量(方案二),将数据表扩展到需要的大小,并移动数据。

我觉得 data.table 应该能够处理这个问题,并且由于效率高,更愿意使用这个包的解决方案。

r data.table transformation
1个回答
4
投票

我不知道如何解决这个问题。melt但你可以使用一个简单的 rbind 比如说

res <- rbind(DT[, c(1,2:3)], 
             DT[, c(1,4:5)], 
                 use.names = FALSE)[service1 != ""]
res
#     customer service1 fee1
#  1:        1        1  100
#  2:        2        3  290
#  3:        2        5  500
#  4:        3        1  100
#  5:        3        3  300
#  6:        3        5  500
#  7:        2        4  400
#  8:        3        2  200
#  9:        3        4  390
# 10:        3        8  800

根据你的第二种输出,你可以尝试像这样的东西

Range <- range(as.numeric(unlist(DT[, c(1, 4)])), na.rm = TRUE)
res[, service1 := factor(service1, levels = Range[1L]:Range[2L])]
dcast(res, customer ~ service1, drop = FALSE, fill = "", value.var = "fee1")
#    customer   1   2   3   4   5 6 7   8
# 1:        1 100                        
# 2:        2         290 400 500        
# 3:        3 100 200 300 390 500     800
© www.soinside.com 2019 - 2024. All rights reserved.