12

これは、私がいつもループを書いてしまうおもちゃの例です。ワンライナーを理解するのに苦労しています。確かに見たことはありますが、くっつきませんでした。

smallFrame <- data.frame(colA = c('A', 'B', 'C' ,'D'), colB = c(1,1,1,1))
someList <- list(A=20, B=30, C=40, D=50)
for(letter in names(someList)){
  smallFrame[smallFrame$colA==letter, 'newColumn'] <- someList[[letter]]
}

1行でループするにはどうすればよいですか? これではいけません。

lapply(names(someList), function(x) {smallFrame[smallFrame$colA==x, 'newColumn'] <- someList[[x]]})
4

2 に答える 2

10

醜いですが、動作します:

lapply(names(someList), function(x) {smallFrame[smallFrame$colA==x, 'newColumn'] <<- someList[[x]]})

に注意してください<<-。機能しない理由<-は、 someList のコピーが関数内で変更されているためです。

ここで「醜い」とは、2 つの理由から、この構文を使用してはならないことを意味します。まず、副作用のある関数はエラーを起こしやすいです。次に、 の戻り値lapplyは無視されます。これらのいずれも、明示的なループが最適であることを示唆しています。

見苦しくなく、@thelatemail からほとんど盗まれました:

smallFrame$newColumn <- unlist(someList[match(smallFrame$colA, names(someList))])

例:

smallFrame <- data.frame(colA = c('A', 'B', 'C' ,'D', 'A'), colB = c(1,1,1,1,1))
> smallFrame

> smallFrame
  colA colB
1    A    1
2    B    1
3    C    1
4    D    1
5    A    1

smallFrame$newColumn <- unlist(someList[match(smallFrame$colA, names(someList))])

> smallFrame
  colA colB newColumn
1    A    1        20
2    B    1        30
3    C    1        40
4    D    1        50
5    A    1        20
于 2013-01-10T23:49:45.413 に答える
7

smallList適切に形状を変更すれば、これは単純なマージです

# reshape2 for melt.
library(reshape2)
# slightly expanded version with duplicate colA == A
smallFrame <- data.frame(colA = c('A', 'A', 'B', 'C' ,'D'), colB = c(1,2,1,1,1))
someList <- list(A=20, B=30, C=40, D=50)
merge(smallFrame, melt(someList), by.x = 'colA', by.y = 'L1')

  colA colB value
1    A    1    20
2    A    2    20
3    B    1    30
4    C    1    40
5    D    1    50

または、smallFrame 内で効率的に割り当てることに本当に熱心な場合は、data.table

library(data.table)
smallDT <- data.table(smallFrame, key = 'colA')
someDT <- data.table(melt(someList), key = 'L1')

# left join smallDT and someDT, assigning the `value` column by reference
# within smallDT as the column `newColumn`
smallDT[someDT, newColumn := value]




smallDT
   colA colB newColumn
1:    A    1        20
2:    A    2        20
3:    B    1        30
4:    C    1        40
5:    D    1        50
于 2013-01-11T00:01:50.177 に答える