3

私はこれについて頭を悩ませてきました。2 つのデータ フレームがあります。df

df <- data.frame(group = 1:3,
                 age = seq(30, 50, length.out = 3),
                 income = seq(100, 500, length.out = 3),
                 assets = seq(500, 800, length.out = 3))

weights

weights <- data.frame(age = 5, income = 10)

これら 2 つのデータ フレームを同じ列名に対してのみ乗算したいと思います。私はこのようなことを試しました:

colwise(function(x) {x * weights[names(x)]})(df)

but that obviously didn't work as colwise does not keep the column name inside the function. I looked at various mapply solutions (example), but I am unable to come up with an answer.

The resulting data.frame should look like this:

structure(list(group = 1:3, age = c(150, 200, 250), income = c(1000, 
3000, 5000), assets = c(500, 650, 800)), .Names = c("group", 
"age", "income", "assets"), row.names = c(NA, -3L), class = "data.frame")

  group age income assets
1     1 150   1000    500
2     2 200   3000    650
3     3 250   5000    800
4

5 に答える 5

6

sweep()この特定の例では、ここであなたの友達です。df名前が正しい順序で並べられているかどうかに依存しますが、weights並べ替えることができます。

> nams <- names(weights)
> df[, nams] <- sweep(df[, nams], 2, unlist(weights), "*")
> df
  group age income assets
1     1 150   1000    500
2     2 200   3000    650
3     3 250   5000    800

weightsとの変数名がdf同じ順序でない場合は、次のようにすることができます。

> df2 <- data.frame(group = 1:3,
+                   age = seq(30, 50, length.out = 3),
+                   income = seq(100, 500, length.out = 3),
+                   assets = seq(500, 800, length.out = 3))
> nams <- c("age", "income") ## order in df2
> weights2 <- weights[, rev(nams)]
> weights2  ## wrong order compared to df2
  income age
1     10   5
> df2[, nams] <- sweep(df2[, nams], 2, unlist(weights2[, nams]), "*")
> df2
  group age income assets
1     1 150   1000    500
2     2 200   3000    650
3     3 250   5000    800

つまり、ageincomeが正しい順序になるように、すべてのオブジェクトを並べ替えます。

于 2012-10-22T20:43:00.423 に答える
4

誰かが plyr でそれを行うための巧妙な方法を持っているかもしれませんが、これはおそらくベース R で最も簡単な方法です。

shared.names <- intersect(names(df), names(weights))
cols <- sapply(names(df), USE.NAMES=TRUE, simplify=FALSE, FUN=function(name) 
        if (name %in% shared.names) df[[name]] * weights[[name]] else df[[name]])
data.frame(do.call(cbind, cols))

#   group age income assets
# 1     1 150   1000    500
# 2     2 200   3000    650
# 3     3 250   5000    800
于 2012-10-22T20:32:24.360 に答える
3

あなたのデータ:

df <- data.frame(group = 1:3, 
                 age = seq(30, 50, length.out = 3), 
                 income = seq(100, 500, length.out = 3), 
                 assets = seq(500, 800, length.out = 3))
weights <- data.frame(age = 5, income = 10)

ロジック:

# Basic name matching looks like this
names(df[names(df) %in% names(weights)])
# [1] "age"    "income"

# Use that in `sapply()`
sapply(names(df[names(df) %in% names(weights)]), 
       function(x) df[[x]] * weights[[x]])
#      age income
# [1,] 150   1000
# [2,] 200   3000
# [3,] 250   5000

実装:

# Put it all together, replacing the original data
df[names(df) %in% names(weights)] <- sapply(names(df[names(df) %in% names(weights)]), 
                                            function(x) df[[x]] * weights[[x]])

結果:

df
#   group age income assets
# 1     1 150   1000    500
# 2     2 200   3000    650
# 3     3 250   5000    800
于 2012-10-22T20:37:18.123 に答える
2

ここに data.table解決策があります

library(data.table)
DT <- data.table(df)
W <- data.table(weights)

mapply(または) を使用Mapして新しい列を計算し、参照によって両方を一度に追加します。

DT <- data.table(df)
W <- data.table(weights)


DT[, `:=`(names(W), Map('*', DT[,names(W), with = F], W)), with = F]
于 2012-10-22T22:00:11.377 に答える
0

which(%in%)の結果のインデックスを使用して、forループでこれを行うこともできます。上記のアプローチははるかに効率的ですが、これは代替手段です。

results <- list()
  for ( i in 1:length(which(names(df) %in% names(weights))) ) {
    idx1 <- which(names(df) %in% names(weights))[i]
      idx2 <- which(names(weights) %in% names(df))[i] 
    results[[i]] <- dat[,idx1] * weights[idx2] 
  } 
unlist(results)  
于 2012-10-22T20:41:05.837 に答える