循环以跨列相乘
loop to multiply across columns
我有一个数据框,其中的列标记为 sales1
、sales2
、price1
、price2
,我想通过乘以 sales1
* 来计算收入price1
以迭代方式遍历每个数字等等。
data <- data_frame(
"sales1" = c(1, 2, 3),
"sales2" = c(2, 3, 4),
"price1" = c(3, 2, 2),
"price2" = c(3, 3, 5))
data
# A tibble: 3 x 4
# sales1 sales2 price1 price2
# <dbl> <dbl> <dbl> <dbl>
#1 1 2 3 3
#2 2 3 2 3
#3 3 4 2 5
为什么以下代码不起作用?
data %>%
mutate (
for (i in seq_along(1:2)) {
paste0("revenue",i) = paste0("sales",i) * paste0("price",i)
}
)
假设您的列已经订购(sales1
、sales2
、price1
、price2
)。我们可以将数据帧分成两部分,然后将它们相乘
data[grep("sales", names(data))] * data[grep("price", names(data))]
# sales1 sales2
#1 3 6
#2 4 9
#3 6 20
如果列还没有根据它们的名称排序,我们可以使用order
对它们进行排序,然后使用上面的命令。
data <- data[order(names(data))]
这个回答并不简短。为此,@RonakShah 的现有答案值得一看!
我的回复旨在解决一个更广泛的问题,即在 tidyverse
中尝试这样做的难度。我的理解是这很难,因为数据当前不是 "tidy" 格式。相反,您可以像这样创建一个整洁的数据框:
library(tidyverse)
tidy_df <- data %>%
rownames_to_column() %>%
gather(key, value, -rowname) %>%
extract(key, c("variable", "id"), "([a-z]+)([0-9]+)") %>%
spread(variable, value)
这使得最终的计算变得简单
tidy_df %>% mutate(revenue = sales * price)
#> # A tibble: 6 x 5
#> rowname id price sales revenue
#> <chr> <chr> <dbl> <dbl> <dbl>
#> 1 1 1 3 1 3
#> 2 1 2 3 2 6
#> 3 2 1 2 2 4
#> 4 2 2 3 3 9
#> 5 3 1 2 3 6
#> 6 3 2 5 4 20
如果您需要将数据恢复为原始格式,您可以这样做,尽管我觉得这很笨拙(我相信这可以通过某种方式改进)。
tidy_df %>% mutate(revenue = sales * price) %>%
gather(key, value, -c(rowname, id)) %>%
unite(key, key, id, sep = "") %>%
spread(key, value) %>%
select(starts_with("price"),
starts_with("sales"),
starts_with("revenue"))
#> # A tibble: 3 x 6
#> price1 price2 sales1 sales2 revenue1 revenue2
#> * <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 3 3 1 2 3 6
#> 2 2 3 2 3 4 9
#> 3 2 5 3 4 6 20
我有一个数据框,其中的列标记为 sales1
、sales2
、price1
、price2
,我想通过乘以 sales1
* 来计算收入price1
以迭代方式遍历每个数字等等。
data <- data_frame(
"sales1" = c(1, 2, 3),
"sales2" = c(2, 3, 4),
"price1" = c(3, 2, 2),
"price2" = c(3, 3, 5))
data
# A tibble: 3 x 4
# sales1 sales2 price1 price2
# <dbl> <dbl> <dbl> <dbl>
#1 1 2 3 3
#2 2 3 2 3
#3 3 4 2 5
为什么以下代码不起作用?
data %>%
mutate (
for (i in seq_along(1:2)) {
paste0("revenue",i) = paste0("sales",i) * paste0("price",i)
}
)
假设您的列已经订购(sales1
、sales2
、price1
、price2
)。我们可以将数据帧分成两部分,然后将它们相乘
data[grep("sales", names(data))] * data[grep("price", names(data))]
# sales1 sales2
#1 3 6
#2 4 9
#3 6 20
如果列还没有根据它们的名称排序,我们可以使用order
对它们进行排序,然后使用上面的命令。
data <- data[order(names(data))]
这个回答并不简短。为此,@RonakShah 的现有答案值得一看!
我的回复旨在解决一个更广泛的问题,即在 tidyverse
中尝试这样做的难度。我的理解是这很难,因为数据当前不是 "tidy" 格式。相反,您可以像这样创建一个整洁的数据框:
library(tidyverse)
tidy_df <- data %>%
rownames_to_column() %>%
gather(key, value, -rowname) %>%
extract(key, c("variable", "id"), "([a-z]+)([0-9]+)") %>%
spread(variable, value)
这使得最终的计算变得简单
tidy_df %>% mutate(revenue = sales * price)
#> # A tibble: 6 x 5
#> rowname id price sales revenue
#> <chr> <chr> <dbl> <dbl> <dbl>
#> 1 1 1 3 1 3
#> 2 1 2 3 2 6
#> 3 2 1 2 2 4
#> 4 2 2 3 3 9
#> 5 3 1 2 3 6
#> 6 3 2 5 4 20
如果您需要将数据恢复为原始格式,您可以这样做,尽管我觉得这很笨拙(我相信这可以通过某种方式改进)。
tidy_df %>% mutate(revenue = sales * price) %>%
gather(key, value, -c(rowname, id)) %>%
unite(key, key, id, sep = "") %>%
spread(key, value) %>%
select(starts_with("price"),
starts_with("sales"),
starts_with("revenue"))
#> # A tibble: 3 x 6
#> price1 price2 sales1 sales2 revenue1 revenue2
#> * <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 3 3 1 2 3 6
#> 2 2 3 2 3 4 9
#> 3 2 5 3 4 6 20