假设我在一家为其客户提供多种不同服务的公司工作。我收到了一份关于我需要分析的服务的数据报告。报告的格式化方式易于阅读和打印,但不适合数据分析。
报告的格式如下:
输入:
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
有许多客户,每个客户都有许多服务消费和相应的费用。服务和费用水平打印成四列,然后溢出到一个新行。每个客户可以有任意数量的服务,但每个服务只能为每个客户发生一次,并且每个客户的服务费用可能不同。它们可能总是以相同的顺序打印,但解决方案不应该依赖于此。
任务是将数据转换为可用格式。我看到两种不同的方法来做到这一点。
第一个选项(长格式):切掉最后两列,为每个客户创建一个新行,并填写内容。
选项一看起来像这样:
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
我可以处理任何一种格式(长和宽之间的转换相当容易)。
作为一个起点,我认为我必须找到每个客户的服务数量(选项1)或唯一服务的数量(选项2),将数据表扩展到所需的大小并移动数据。
我觉得data.table
应该能够解决这个问题,并且由于其效率,我更倾向于使用此软件包。
答案 0 :(得分:4)
我不知道如何使用 java.lang.NullPointerException
at android.support.v7.widget.RecyclerView.findMinMaxChildLayoutPositions(RecyclerView.java:2537)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2324)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:2709)
at android.view.View.layout(View.java:14339)
at android.view.ViewGroup.layout(ViewGroup.java:4612)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1141)
at android.view.View.layout(View.java:14339)
at android.view.ViewGroup.layout(ViewGroup.java:4612)
at android.widget.FrameLayout.onLayout(FrameLayout.java:507)
at android.view.View.layout(View.java:14339)
at android.view.ViewGroup.layout(ViewGroup.java:4612)
at android.widget.FrameLayout.onLayout(FrameLayout.java:507)
at android.view.View.layout(View.java:14339)
at android.view.ViewGroup.layout(ViewGroup.java:4612)
at android.widget.FrameLayout.onLayout(FrameLayout.java:507)
at android.view.View.layout(View.java:14339)
at android.view.ViewGroup.layout(ViewGroup.java:4612)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2276)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2040)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1222)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5000)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:776)
at android.view.Choreographer.doCallbacks(Choreographer.java:579)
at android.view.Choreographer.doFrame(Choreographer.java:548)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:762)
at android.os.Handler.handleCallback(Handler.java:800)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5463)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:854)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:621)
at dalvik.system.NativeStart.main(Native Method)
解决这个问题,但你可以在这里使用简单的melt
,例如
rbind
根据您的第二个输出,您可以尝试类似
的内容res <- rbind(DT[, c(1,2:3), with = FALSE],
DT[, c(1,4:5), with = FALSE],
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