在R中计算数据集中等间隔总数的百分比。

3

我正在处理一个数据集,其中包含每个FMCG类别的总销售额以及它在各主要渠道上的销售分布情况,如下所示:

CTY  totsal MTsal   GTsal   Othsal  totsal  MTsal   GTsal   Othsal
     food   food    food    food    deo      deo    deo      deo
Arg  47313  19620   15052   12641   178      113    41       24
Aus  143140 85172   4634    53334   459      438    5        16
Bel  125399 82966   7818    34614   424      229    5        190

在我的输出数据集中,我希望计算每个第4列所在的总类别组的份额,例如totsal food和totsal deo。因此,这些产品的份额必须为1,而加起来总和的渠道的份额应为它们各自的值。我要查看的示例输出如下:
CTY totshar MTshar  GTshar  Othshar totshar MTshar  GTshar  Othshar
    food    food    food    food    deo      deo    deo      deo
Arg  1      0.4     0.3     0.3     1.0      0.6    0.2      0.1
Aus  1      0.6     0.0     0.4     1.0      1.0    0.0      0.0
Bel  1      0.7     0.1     0.3     1.0      0.5    0.0      0.4

上面的例子是一个摘录,我需要增加灵活性以包括尽可能多的类别和国家。

你能发布一下你的数据框的摘录吗?(只需要 dput(head(df)) - RoyalTS
嗨,不确定你的意思。我展示的例子是一部分。这里有8列,其中第1列是第2、3、4列的总和,第5列是第6、7、8列的总和。整个数据集都是这样进行的。 - user36176
1个回答

4
你可以像这样做。首先,我复制并粘贴了你的数据:
d <- read.table("clipboard",header=T)
d
   CTY totsal MTsal GTsal Othsal totsal.1 MTsal.1 GTsal.1 Othsal.1
1 <NA>   food  food  food   food      deo     deo     deo      deo
2  Arg  47313 19620 15052  12641      178     113      41       24
3  Aus 143140 85172  4634  53334      459     438       5       16
4  Bel 125399 82966  7818  34614      424     229       5      190

然后我将数字转换为数字矩阵

m <- data.frame(d[-1, -1])
m <- t(apply(m, 1, function(x) as.numeric(as.character(x))))
m
    [,1]  [,2]  [,3]  [,4] [,5] [,6] [,7] [,8]
2  47313 19620 15052 12641  178  113   41   24
3 143140 85172  4634 53334  459  438    5   16
4 125399 82966  7818 34614  424  229    5  190

我使用 grep 查找了总列数并为列组创建了索引gr。需要注意的是,total 列必须始终是该组的第一列。组值的总数可以有所变化。

gr_total <- grep("tot", colnames(d)[-1])
gr <- sort(rep(gr_total, 4))

我使用了sapply函数来计算每个组的百分比,并使用matrix函数转换结果。sapply函数“循环”遍历由grep搜索找到的所有组。在function(x, y, z)中,它对属于该组的所有列进行了子集划分。这里是第一个m[, gr == gr_total[1]]。因为R优化了矢量化处理,所以可以将向量/矩阵除以向量。尝试m[, gr == gr_total[1]]/m[ , gr_total[1]]。有关matrix()函数,请参见?matrix并检查sapply输出。

matrix(sapply(gr_total, function(x, y, z)  z[, y==x]/z[, x], gr, m), nrow(m), ncol(m), byrow = FALSE)
     [,1]      [,2]       [,3]      [,4] [,5]      [,6]       [,7]       [,8]
[1,]    1 0.4146852 0.31813666 0.2671782    1 0.6348315 0.23033708 0.13483146
[2,]    1 0.5950258 0.03237390 0.3726003    1 0.9542484 0.01089325 0.03485839
[3,]    1 0.6616161 0.06234499 0.2760309    1 0.5400943 0.01179245 0.44811321

您可以使用round函数将数字四舍五入为一位。假设您将结果保存在m1中,请使用round(m1, 1)

您可以通过colnames(m1) <- colnames(d)[-1]替换列名。若要添加列和行,请参见rbindcbind


完美运行。您能详细解释一下最后的sapply和matrix代码吗?此外,我没有得到原始数据集中的列名。我得到的是V1、V2等等,有没有办法将它们替换为原始列名或者重新获取这些列名? - user36176

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接