假设我有一个数据框,其中有多个组件,并且它们的属性列在多列中,我想对列运行多个函数。我的方法是尝试将其基于每个列标题中的子字符串,但我还没有能够弄清楚如何做到这一点。以下是数据框的示例。
Basket F_Type_1 F_Qty_1 F_P_1 F_Type_2 F_Qty_2 F_P_2
AAA Apple 10 2.5 Banana 9 2
BBB Peach 5 6 Melon 20 5
我基本上想要在这个数据帧的末尾添加两个新列,它们将Qty和P相乘,这样你就会得到两个新的列,如下所示。
F_Total_1 F_Total_2
25 18
30 100
输入是动态的,所以有时它可能是2个水果或10个水果在某些篮子里。但是我可以把这个部分弄清楚,它还试图找出如何根据子串#1'来计算列数。或者' 2'。
感谢您的所有帮助以及您可能采取的任何其他方法!
答案 0 :(得分:2)
我们创建一个查找特定名称的函数,然后计算rowwise产品。这个函数的重要提升者是mapply
函数。我们添加了最后一步来重命名结果[@-1,0:0='<',<7>,1:0]
[@-1,1:4='item',<16>,1:1]
[@-1,5:5='>',<10>,1:5]
[@-1,6:8='\n ',<6>,1:6]
[@-1,9:42='<![CDATA[',<2>,2:2]
[@-1,9:42='\n My CDATA Block\n ',<19>,2:2]
[@-1,9:42=']]>',<18>,2:2]
[@-1,43:43='\n',<6>,4:5]
[@-1,44:44='<',<7>,5:0]
[@-1,45:45='/',<13>,5:1]
[@-1,46:49='item',<16>,5:2]
[@-1,50:50='>',<10>,5:6]
。
data.frame
答案 1 :(得分:1)
创建数据
library(data.table)
df <- fread("
Basket F_Type_1 F_Qty_1 F_P_1 F_Type_2 F_Qty_2 F_P_2
AAA Apple 10 2.5 Banana 9 2
BBB Peach 5 6 Melon 20 5
")
df
# Basket F_Type_1 F_Qty_1 F_P_1 F_Type_2 F_Qty_2 F_P_2
# 1: AAA Apple 10 2.5 Banana 9 2
# 2: BBB Peach 5 6.0 Melon 20 5
对于从1到sum(grepl('F_P_', names(df)))
的数字,请将F_Total_{number}
设为F_Qty_{number}*F_P_{number}
for(i in seq(sum(grepl('F_P_', names(df)))))
df[, paste0('F_Total_', i) := Reduce(`*`, .SD)
, .SDcols = paste0(c('F_Qty_', 'F_P_'), i)]
df
# Basket F_Type_1 F_Qty_1 F_P_1 F_Type_2 F_Qty_2 F_P_2 F_Total_1 F_Total_2
# 1: AAA Apple 10 2.5 Banana 9 2 25 18
# 2: BBB Peach 5 6.0 Melon 20 5 30 100
或在基数R中,df
为data.frame
for(i in seq(sum(grepl('F_P_', names(df)))))
df[paste0('F_Total_', i)] <- Reduce(`*`, df[paste0(c('F_Qty_', 'F_P_'), i)])
答案 2 :(得分:1)
在基础R中,您可以使用[[]]
表单来访问带字符串的列,这样您就可以轻松循环
df <- read.table(text = "Basket F_Type_1 F_Qty_1 F_P_1 F_Type_2 F_Qty_2 F_P_2
AAA Apple 10 2.5 Banana 9 2
BBB Peach 5 6 Melon 20 5",header = T)
for(i in 1:2)
{
df[[paste0("F_Total_",i)]] <- as.numeric(df[[paste0("F_P_",i)]])*as.numeric(df[[paste0("F_Qty_",i)]])
}
Basket F_Type_1 F_Qty_1 F_P_1 F_Type_2 F_Qty_2 F_P_2 F_Total_1 F_Total_2
1 AAA Apple 10 2.5 Banana 9 2 25 18
2 BBB Peach 5 6.0 Melon 20 5 30 100
答案 3 :(得分:1)
这是一种使用tidyverse
函数重塑数据的方法。基本上使用tidyr
动词,我们将您的数据重塑为更“整洁”的格式。
# library(dplyr); library(tidyr)
dd %>% select(Basket, contains("_Qty_"), contains("_P_")) %>%
gather("key", "value", -Basket) %>%
separate(key, c("F", "Val", "Grp")) %>%
group_by(Basket, Grp) %>%
spread(Val, value) %>%
mutate(Total=P*Qty, GrpN=paste0("Total_", Grp)) %>%
ungroup() %>%
select(Basket, GrpN, Total) %>%
spread(GrpN ,Total)
# Basket Total_1 Total_2
# <fct> <dbl> <dbl>
# 1 AAA 25 18
# 2 BBB 30 100
答案 4 :(得分:1)
setNames(df[grepl("F_Qty",names(df))]*df[grepl("F_P",names(df))],paste0("F_Total_",1:2))
F_Total_1 F_Total_2
1 25 18
2 30 100
答案 5 :(得分:0)
建议:如果您可以以长格式存储数据,它将使未来的维护更加清洁。
Basket Item Type Qty Price Total
AAA 1 Apple 10 2.5 25
AAA 2 Banana 9 2 18
BBB 1 Peach 5 6.0 30
BBB 2 Melon 20 5 100
BBB 3 Orange 11 2.7 29.7
然后,当您确实需要上述格式的数据时,请使用data.table
包来转置数据。
library(data.table)
fruits <- data.frame("Basket" = c("AAA", "AAA", "BBB", "BBB", "BBB"),
"Item" = c(1,2,1,2,3),
"Type" = c("Apple", "Banana", "Peach", "Melon", "Orange"),
"Qty" = c(10, 9, 5, 20, 11),
"Price" = c(2.5, 2, 6.0, 5, 2.7)
)
fruits$Total <- fruits$Qty * fruits$Price
fruits.New <- data.table::dcast(setDT(fruits),
formula = Basket ~ Item,
value.var = c("Type", "Price", "Qty", "Total"))
这样,您只需维护一个公式而不必担心apply
,同时也可以灵活地使用可变列号。
如果列名称很重要,则应该相对容易修复。