我有一个data.frame df
df = data.frame(v = c('E', 'B', 'EB', 'RM'))
df$n= 100 / apply(df, 1, nchar)
其中v
代表值E = 4
,B = 3
,R = 2
和M = 1
我想像这样计算一列:
v n idx
1 E 100 400
2 B 100 300
3 EB 50 350
4 RM 50 150
其中idx为n (v)
。例如,第一行4 * 100 = 400
和最后一行(2 + 1) * 50 = 150
我有这样的事情:
df$e = ifelse(grepl('E', df$v), 4, 0)
df$b = ifelse(grepl('B', df$v), 3, 0)
df$r = ifelse(grepl('R', df$v), 2, 0)
df$m = ifelse(grepl('M', df$v), 1, 0)
df$idx = df$n * (df$e + df$b + df$r + df$m)
但随着列数的增加,它变得不可行。
答案 0 :(得分:3)
1)定义一个查找表lookup
和一个带有单个字母向量的函数Sum
,查找每个字母并将它们的查找数相加。
将v
分成单个字母和sapply
的向量列表,使用Sum
将结果按n
进行操作。
lookup <- c(E = 4, B = 3, R = 2, M = 1)
Sum <- function(x) sum(lookup[x])
transform(df, idx = n * sapply(strsplit(as.character(v), ""), Sum))
,并提供:
v n idx
1 E 100 400
2 B 100 300
3 EB 50 350
4 RM 50 150
2)上面使用lookup
的替代方法是v
中的每个字符使用在公式表示法创建中表示的匿名函数来应用lookup
我们sapply
sum
的列表,最后乘以n
。
library(gsubfn)
transform(df, idx = n * sapply(strapply(as.character(v), ".", x ~ lookup[x]), sum))
3)以上使用lookup
的dplyr / tidyr解决方案如下。我们插入id
来唯一标识每一行,并使用separate_rows
将v
的每个字母放在一个单独的行中。然后,我们通过查找每个字母和求和来汇总具有相同id的所有行。最后,我们删除id
。
library(dplyr)
library(tidyr)
df %>%
mutate(id = 1:n()) %>%
separate_rows(v, sep = "(?<=.)(?=.)") %>%
group_by(id, n) %>%
summarize(idx = sum(n * lookup[v])) %>%
ungroup %>%
select(-id)
,并提供:
# A tibble: 4 x 3
id n idx
<int> <dbl> <dbl>
1 1 100. 400.
2 2 100. 300.
3 3 50. 350.
4 4 50. 150.
可以通过用这两个语句替换separate_rows
语句来避免复杂的正则表达式:
mutate(v = strsplit(as.character(v), "")) %>%
unnest %>%
答案 1 :(得分:1)
使用您的值制作查找表。然后在match
列的拆分版本(通过strsplit
),df$v
相应的值之间sum
进行乘法计算:
lkup <- data.frame(id=c("E","B","R","M"),value=c(4,3,2,1))
sapply(
strsplit(as.character(df$v),""),
function(x) sum(lkup$value[match(x,lkup$id)])
) * df$n
#[1] 400 300 350 150