数据集由如下所示的数字序列组成。我需要一个新列来说明第一个值和最终值之间的平均运动。例如,在第一行中,数字为(1、3、5、2),因此平均运动为average(abs(3-1),abs(5-1),abs(2-1)),即2.333
Sl no Column A req
1 1 > 3 > 5 > 2 2.333
2 2 > 5 > 1 > 10 > 5 3.75
有没有办法解决这个问题?
答案 0 :(得分:1)
1)dplyr / tidyr 假设输入DF
在末尾的注释中可重复显示,请将Column A
分成单独的行,对其进行汇总并加入新的req列到原始数据帧上。
library(dplyr)
library(tidyr)
Req <- DF %>%
separate_rows(`Column A`, convert = TRUE) %>%
group_by(`Sl no`) %>%
summarize(req = mean(abs(`Column A`[-1] - `Column A`[1]))) %>%
ungroup
DF %>% inner_join(Req)
## Joining, by = "Sl no"
## Sl no Column A req
## 1 1 1 > 3 > 5 > 2 2.333333
## 2 2 2 > 5 > 1 > 10 > 5 3.750000
2)基本R 使用AvgAbsDiff
的基本R解决方案采用Column A
中形式的字符串,使用scan
进行读取并计算req
。然后将其应用于每一行。
AvgAbsDiff <- function(x) {
z <- scan(text = x, sep = ">", quiet = TRUE)
mean(abs(z[-1] - z[1]))
}
transform(DF, req = sapply(as.character(`Column A`), AvgAbsDiff),
row.names = NULL, check.names = FALSE)
## Sl no Column A req
## 1 1 1 > 3 > 5 > 2 2.333333
## 2 2 2 > 5 > 1 > 10 > 5 3.750000
2a)此基本解决方案不使用任何* apply函数。使用Column A
将read.table
读入数据帧,然后从中计算出req
。
r <- read.table(text = as.character(DF$`Column A`), header = FALSE,
sep = ">", fill = NA)
transform(DF, req = rowMeans(abs(r[, -1] - r[, 1]), na.rm = TRUE),
check.names = FALSE)
## Sl no Column A req
## 1 1 1 > 3 > 5 > 2 2.333333
## 2 2 2 > 5 > 1 > 10 > 5 3.750000
DF <-
structure(list(`Sl no` = 1:2, `Column A` = structure(1:2,
.Label = c("1 > 3 > 5 > 2",
"2 > 5 > 1 > 10 > 5"), class = "factor")),
class = "data.frame", row.names = c(NA, -2L))
答案 1 :(得分:0)
您可以执行以下操作:
data$req <- sapply(data$columnA,
function(x) mean(abs(diff(as.integer(unlist(strsplit(x, ' > ')))))))
sapply
会将功能应用于columnA
的每个元素。
然后,从内向外进行操作:
strsplit
在“>”上的columnA中拆分元素,结果是:
[[1]]
[1] "1" "3" "5" "2"
unlist
将结果转换为向量:
"1" "3" "5" "2"
as.integer
转换为数字:
1 3 5 2
diff
来计算数字之间的差:
2 2 -3
abs
取绝对值:
2 2 3
最后是mean
以取平均值:
2.333333
编辑:稍微误解了问题,这样可以正确计算出结果:
my.df$req <- sapply(my.df$columnA,
function(x) {
tmp <- as.integer(unlist(strsplit(x, ' > ')))
mean(abs(tmp[2:length(tmp)] - tmp[1]))
})
答案 2 :(得分:0)
以下代码有效,但是可以用更好的方式编写。无论如何..
让我先重新创建您的数据框
q <- data.frame(Sl_no=1:2, Column_A=c(("1 > 3 > 5 > 2"), (" 2 > 5 > 1 > 10 > 5")))
q$req <- NA
哪个给了我们
Sl_no Column_A req
1 1 > 3 > 5 > 2 NA
2 2 > 5 > 1 > 10 > 5 NA
接下来,让我们将此序列拆分为一个R列表:
q$A <- strsplit(as.character(q$Column_A), " > ")
并添加此列表的长度:
q$A_length <- lengths(q$A)
然后,我们创建一个循环,该循环将遍历元素2:序列中的最后一个元素,从中减去序列中的第一个数字并存储在列表中。在内部循环的最后,我们将该值的平均值存储在req
列的相应行中。
for (row in 1:nrow(q)) {
sum = c()
for (number in 2:q$A_length[row]) {
sum <- c(sum, as.numeric(q$A[[row]][number]) - as.numeric(q$A[[row]][1]))
}
q$req[row] <- mean(sum)
}
最后,让我们打印创建的数据框:
Sl_no Column_A A A_length req
1 1 > 3 > 5 > 2 1, 3, 5, 2 4 2.333333
2 2 > 5 > 1 > 10 > 5 2, 5, 1, 10, 5 5 3.250000
希望这会有所帮助!