使用以下代碼:
val_a <- c("2", "4", "6", "8")
divide_a <- c(1, 2, 3, 4)
val_b <- c("62", "42", "56", "28")
divide_b <- c(11, 12, 22, 44)
val_c <- c("652", "142", "546", "298")
divide_c <- c(74, 23, 112, 64)
df <- as.data.frame(cbind(val_a, divide_a, val_b, divide_b, val_c, divide_c))
給出以下資料框:
val_a divide_a val_b divide_b val_c divide_c
1 2 1 62 11 652 74
2 4 2 42 12 142 23
3 6 3 56 22 546 112
4 8 4 28 44 298 64
我試圖將三組值的“val”除以“divide”,給出如下內容:
val_a divide_a val_b divide_b val_c divide_c result_ a result_b result_c
1 2 1 62 11 652 74 2 5,6 8,8
2 4 2 42 12 142 23 4 3,8 6,2
3 6 3 56 22 546 112 etc.
4 8 4 28 44 298 64
到目前為止,我一直在嘗試使用 for 回圈:
for(i in 1:ncol(df)) { # for-loop over columns
df[ , paste0("result", i)] <- as.numeric((df[ ,i]))/as.numeric((df[ ,i 1]))
}
問題是:
- 當它應該跳過一列時,它將每一列除以下一列(例如,不將“divide_a”除以“val_b”)
- 不命名列
我不知所措,希望能得到任何幫助。我的實際資料框有超過 1000 列,所以我不想手動執行此操作。謝謝你。
uj5u.com熱心網友回復:
我確信在 base R 中有一種簡潔(但對我來說難以理解)的方法來做到這一點,但我個人對這類問題的偏好是使用dplyr/tidyr來重塑資料并保持簡單。
下面的代碼將采用任意數量的“val”/“divide”對并計算比率。
library(tidyverse)
df %>%
mutate(row = row_number()) %>%
pivot_longer(-row, names_to = c("operation", "group"),
names_sep = "_", values_transform = as.numeric) %>%
pivot_wider(names_from = operation, values_from = value) %>%
mutate(result = val / divide)
首先,我添加了一個行號變數來幫助跟蹤整形步驟之間的資料。然后我pivot_longer將原始資料列轉換為三個新列,“操作”、“組”和“值”(這是默認名稱)。然后我根據“操作”重塑更寬,然后將每個除val以其相關divide值很簡單。
此時的結果是
# A tibble: 12 × 5
row group val divide result
<int> <chr> <dbl> <dbl> <dbl>
1 1 a 2 1 2
2 1 b 62 11 5.64
3 1 c 652 74 8.81
4 2 a 4 2 2
5 2 b 42 12 3.5
6 2 c 142 23 6.17
7 3 a 6 3 2
8 3 b 56 22 2.55
9 3 c 546 112 4.88
10 4 a 8 4 2
11 4 b 28 44 0.636
12 4 c 298 64 4.66
但如果需要,我們可以重塑它。我們可以添加到上面的鏈中:
... %>%
select(-val, -divide) %>%
pivot_wider(names_from = group, names_prefix = "result_",
values_from = result)
要得到:
# A tibble: 4 × 4
row result_a result_b result_c
<int> <dbl> <dbl> <dbl>
1 1 2 5.64 8.81
2 2 2 3.5 6.17
3 3 2 2.55 4.88
4 4 2 0.636 4.66
uj5u.com熱心網友回復:
for loop方式是
key <- str_remove(names(df)[startsWith(names(df), "val_")], "val_")
for (i in key){
col1 <- paste0("val_", i)
col2 <- paste0("divide_", i)
col3 <- paste0("result_", i)
df[col3] <- as.numeric(df[,col1]) / as.numeric(df[,col2])
}
df
val_a divide_a val_b divide_b val_c divide_c result_a result_b result_c
1 2 1 62 11 652 74 2 5.6363636 8.810811
2 4 2 42 12 142 23 2 3.5000000 6.173913
3 6 3 56 22 546 112 2 2.5454545 4.875000
4 8 4 28 44 298 64 2 0.6363636 4.656250
uj5u.com熱心網友回復:
試試這個 for 回圈
for(i in 1:(ncol(df)/2)) { # for-loop over columns
j <- 2*i - 1
if(j < ncol(df))
df[[paste0("result", i)]] <- as.numeric((df[ ,j]))/as.numeric((df[ ,j 1]))
}
uj5u.com熱心網友回復:
沒有重塑的簡潔但易于理解的基本 R 版本將是:
vars <- c("a","b","c")
df[paste("result", vars, sep="_")] <- df[paste("val", vars, sep="_")] /
df[paste("divide", vars, sep="_")]
df
# val_a divide_a val_b divide_b val_c divide_c result_a result_b result_c
#1 2 1 62 11 652 74 2 5.6363636 8.810811
#2 4 2 42 12 142 23 2 3.5000000 6.173913
#3 6 3 56 22 546 112 2 2.5454545 4.875000
#4 8 4 28 44 298 64 2 0.6363636 4.656250
dplyr可能性的等效reshape-ing 選項是:
long <- reshape(df, varying=TRUE, direction="long", sep="_")
long$result <- long$val/long$divide
reshape(long, idvar="id", direction="wide", sep="_")
...甚至可以通過|>管道傳輸:
reshape(df, varying=TRUE, direction="long", sep="_") |>
transform(result = val/divide) |>
reshape(idvar="id", direction="wide", sep="_")
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/488544.html
