循环遍历Dataframe的列并将值除以另一个数据帧中列名称索引的值?

时间:2016-02-17 19:26:03

标签: r loops dataframe

我有一个如下所示的数据框,其中有很多列和数据

                 Label 2015-08-24 2015-08-25
   1               AxG   179238.8   174160.3
   2              CHaF   203544.2   199411.9
   3              HHHH   130138.9   129182.2
   4               fLS   146367.0   148708.0
   5               KSU   194584.7   188508.0
   6              MqCC   272922.7   273369.5
   7              BEPU        0.0        0.0
   8              SSEX   107566.4   111552.8
   9               QQQ   248380.4   257064.2
   10              AAA   258735.4   260415.5

我有另一个数据框,其行索引与第一个中的列名相同(在本例中为日期)。我想将第一个数据帧的列中的每个值除以第二个

中的相应值
                      totals
      2015-08-24      1741479
      2015-08-25      199411.9

我的第一个想法是做下面的事情(我来自pythonic背景,虽然不久前)

        > for(i in names(df1)){
         + df1[[df1[,i]/df2[i,]]]

但这是我收到的错误:

  

.subset2(x,i,exact = exact)中的错误:在1级In中没有这样的索引   另外:警告信息:在Ops.factor(权重[,i],   weight_totals [i,]):'/'对因子无意义

有什么想法吗?

3 个答案:

答案 0 :(得分:5)

我们也可以使用sweep。对于必须在数组上应用值向量的任何情况,它都是一个有用的函数。我们选择保证金2来扫描列(我们可以为行选择1):

sweep(df[-1], 2, df2$totals, '/')
#      2015-08-24 2015-08-25
# [1,] 0.10292332  0.8733696
# [2,] 0.11688008  1.0000000
# [3,] 0.07472895  0.6478159
# [4,] 0.08404753  0.7457328
# [5,] 0.11173531  0.9453197
# [6,] 0.15671892  1.3708786
# [7,] 0.00000000  0.0000000
# [8,] 0.06176727  0.5594089
# [9,] 0.14262612  1.2891116
# [10,] 0.14857222  1.3059176

答案 1 :(得分:4)

您可以转置第二个data.frame并使用intersect()

乘以匹配的列
dft <- data.frame(t(df2), check.names = FALSE) # transpose df2

mapply("/", df[intersect(names(df), names(dft))],
        dft[intersect(names(df), names(dft))]) # perfrom division
#      2015-08-24 2015-08-25
# [1,] 0.10292332  0.8733696
# [2,] 0.11688008  1.0000000
# [3,] 0.07472895  0.6478159
# [4,] 0.08404753  0.7457328
# [5,] 0.11173531  0.9453197
# [6,] 0.15671892  1.3708786
# [7,] 0.00000000  0.0000000
# [8,] 0.06176727  0.5594089
# [9,] 0.14262612  1.2891116
#[10,] 0.14857222  1.3059176

使用的数据:

df <- structure(list(Label = structure(c(2L, 4L, 6L, 5L, 7L, 8L, 3L, 
10L, 9L, 1L), .Label = c("AAA", "AxG", "BEPU", "CHaF", "fLS", 
"HHHH", "KSU", "MqCC", "QQQ", "SSEX"), class = "factor"), `2015-08-24` = c(179238.8, 
203544.2, 130138.9, 146367, 194584.7, 272922.7, 0, 107566.4, 
248380.4, 258735.4), `2015-08-25` = c(174160.3, 199411.9, 129182.2, 
148708, 188508, 273369.5, 0, 111552.8, 257064.2, 260415.5)), .Names = c("Label", 
"2015-08-24", "2015-08-25"), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10"))

df2 <- structure(list(totals = c(1741479, 199411.9)), .Names = "totals", row.names = c("2015-08-24", 
"2015-08-25"), class = "data.frame")

答案 2 :(得分:2)

Altough @PierreLafortune具有最短的解决方案,使用sweep要求df的列名称和df2的rownames的顺序必须相同。使用for时(我还想使用@mtoto的intersect方法),df的列名和df2的rownames不必位于获得所需结果的顺序相同。另一个优点是df立即更新:

for(i in names(df)[-1]) 
  df[, i] <- df[, i] / df2$totals[match(i, row.names(df2))]

给出:

> df
   Label 2015-08-24 2015-08-25
1    AxG 0.10292332  0.8733696
2   CHaF 0.11688008  1.0000000
3   HHHH 0.07472895  0.6478159
4    fLS 0.08404753  0.7457328
5    KSU 0.11173531  0.9453197
6   MqCC 0.15671892  1.3708786
7   BEPU 0.00000000  0.0000000
8   SSEX 0.06176727  0.5594089
9    QQQ 0.14262612  1.2891116
10   AAA 0.14857222  1.3059176