在根據 if/else 陳述句對該行的子集進行排序后,我想對每一行應用一個函式。之后用結果填充資料框中的新列。我有超過兩百萬行,因此執行此操作的 for 回圈效率非常低。
給定以下資料框:(為 r2evans 編輯)
df<-as.data.frame(cbind(matrix(LETTERS[1:3], ncol=1),matrix(sample.int(100,size=15),nrow=3,ncol=5))
> df
V1 V2 V3 V4 V5 V6
1 A 77 79 32 5 4
2 B 57 24 68 65 45
3 C 66 60 82 74 22
有沒有辦法在沒有 for 回圈的情況下將以下回圈應用于每一行,因為我實際上有超過 2630800 行?
df$num <- 0
df[2:7] <- sapply(df[2:7],as.numeric)
names(df) <- c("first_name", "sec", "A", "B", "C", "D", "num")
下面的 if 陳述句需要列的名稱:(也編輯為僅排序一次)
for (i in seq_len(nrow(df))) {
row = sort(df[i,3:6])
if (df[i,1]==names(row)[4]) {
df$num[i] = row[3]/(row[3] row[4])
} else {
df$num[i] = row[4]/(row[3] row[4])
}
}
這樣我就得到了這個結果:
> df
first_name sec A B C D num
1 A 77 79 32 5 4 0.2882883
2 B 57 24 68 65 45 0.4887218
3 C 66 60 82 74 22 0.525641
我不知道如何通過申請來做到這一點,在想這樣的事情嗎?雖然這不起作用,我不確定如何合并 if/else 條件:
df$num <- apply(df, 1, function(x) unlist(x[3:6][order(x[3:6])][3]/(x[3:6][order(x[3:6])][3] x[3:6][order(x[3:6])][4])))
uj5u.com熱心網友回復:
這是一個帶有一些硬編碼(列索引)的小蠻力方法。
cols <- 3:6
sorted2 <- t(apply(df[,cols], 1, sort, decreasing = TRUE))[,1:2]
sorted2
# [,1] [,2]
# 1 79 32
# 2 68 65
# 3 82 74
df$num <- ifelse(df[,1] == names(df)[cols][max.col(df[,cols])],
sorted2[,2], sorted2[,1]) /
rowSums(sorted2)
df
# first_name sec A B C D num
# 1 A 77 79 32 5 4 0.2882883
# 2 B 57 24 68 65 45 0.4887218
# 3 C 66 60 82 74 22 0.5256410
筆記:
- 我定義
cols為如果您更改列,則只需更改一次。 - 您的代碼傾向于比較是否
first_name匹配列名,并從中確定是使用列中的“最大值”還是“第二個最大值”值cols,然后將該數字除以兩個最大值的總和。為此,我計算sorted2了第 1 列中的最大值和第 2 列中的第 2 個最大值,使rowSums和 max/2nd-max 訪問立即/容易。 - 我本可以用
df$first_name代替df[,1],你的選擇。
這應該比for回圈 或好得多sapply,因為它是完全矢量化的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/316345.html
