将平均值从列中的第一个值移动到最终值

时间:2018-09-27 11:12:13

标签: r

数据集由如下所示的数字序列组成。我需要一个新列来说明第一个值和最终值之间的平均运动。例如,在第一行中,数字为(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

有没有办法解决这个问题?

3 个答案:

答案 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 Aread.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

希望这会有所帮助!