создать несколько столбцов с применением на фрейме данных - PullRequest
0 голосов
/ 25 марта 2020

Я пытаюсь добавить несколько столбцов на основе значения столбцов и проверки условий. Я получаю хорошие данные, но не могу добавить столбцы, может быть, это невозможно с apply (x, 1, fun), но только с применить (х, 2, весело)? Спасибо за ваше просветление

df <- data.frame(id = 411:420,
                 value = c(10,0,25,0,32,66,45,88,0,23),
                 prod =  c(500,300,400,600,0,800,400,300,200,0)
                 )

add_coll <- function(x) {

if (x["value"] >0  & x["prod"] > 0) {

  varname_v <- paste0("col_",x["id"],"_v")
  varname_p <- paste0("col_",x["id"],"_p")

  print(varname_v)
  print(varname_p)

  df[, varname_v] <- x["value"] #not working
  df[, varname_p] <- 55 #not working
  df$"test" <- 44 #not working

}

else {

  print("not creating columns")
}

}


apply(df,1,add_coll )

это то, что я ожидаю:

df_expected <- data.frame(
                 "id" = 411:420,
                 "value" = c(10,0,25,0,32,66,45,88,0,23),
                 "prod" =  c(500,300,400,600,0,800,400,300,200,0),

                 "col_411_v" =  c(10,0,0,0,0,0,0,0,0,0),
                 "col_411_p" =  c(500,0,0,0,0,0,0,0,0,0),
                 "col_413_v" =  c(0,0,25,0,0,0,0,0,0,0),
                 "col_413_p" =  c(0,0,400,0,0,0,0,0,0,0),
                 "col_416_v" =  c(0,0,0,0,0,66,0,0,0,0),
                 "col_416_p" =  c(0,0,0,0,0,800,0,0,0,0),
                 "col_417_v" =  c(0,0,0,0,0,0,45,0,0,0),
                 "col_417_p" =  c(0,0,0,0,0,0,400,0,0,0),
                 "col_418_v" =  c(0,0,0,0,0,0,0,88,0,0),
                 "col_418_p" =  c(0,0,0,0,0,0,0,300,0,0)

                 )

    id value prod col_411_v col_411_p col_413_v col_413_p col_416_v col_416_p col_417_v col_417_p col_418_v col_418_p
1  411    10  500        10       500         0         0         0         0         0         0         0         0
2  412     0  300         0         0         0         0         0         0         0         0         0         0
3  413    25  400         0         0        25       400         0         0         0         0         0         0
4  414     0  600         0         0         0         0         0         0         0         0         0         0
5  415    32    0         0         0         0         0         0         0         0         0         0         0
6  416    66  800         0         0         0         0        66       800         0         0         0         0
7  417    45  400         0         0         0         0         0         0        45       400         0         0
8  418    88  300         0         0         0         0         0         0         0         0        88       300
9  419     0  200         0         0         0         0         0         0         0         0         0         0
10 420    23    0         0         0         0         0         0         0         0         0         0         0

Ответы [ 2 ]

1 голос
/ 25 марта 2020

Вы можете создать столбец с номером строки, получить данные в широком формате и связать столбцы с исходным набором данных.

library(dplyr)
library(tidyr)

df %>%
  mutate(row = row_number()) %>%
  pivot_wider(names_from = id, values_from = c(value, prod), 
              values_fill = list(value = 0, prod = 0)) %>%
  select(-row) %>%
  bind_cols(df, .) %>%
  mutate_at(-(1:3), ~replace(., prod <= 0, 0))


#    id value prod value_411 value_412 value_413 value_414 value_415 value_416 ...
#1  411    10  500        10         0         0         0         0         0 ...
#2  412     0  300         0         0         0         0         0         0 ...
#3  413    25  400         0         0        25         0         0         0 ...
#4  414     0  600         0         0         0         0         0         0 ...
#5  415    32    0         0         0         0         0         0         0 ...
#6  416    66  800         0         0         0         0         0        66 ...
#7  417    45  400         0         0         0         0         0         0 ...
#8  418    88  300         0         0         0         0         0         0 ...
#9  419     0  200         0         0         0         0         0         0 ...
#10 420    23    0         0         0         0         0         0         0 ...
1 голос
/ 25 марта 2020

Я бы не советовал писать в (глобальную) среду изнутри, применимо "l oop". Если вы действительно хотите это сделать, вы всегда можете использовать хороший clear for l oop.

. Я бы порекомендовал использовать apply в вашем случае - создать data.frame с дополнительными столбцами. и затем добавьте их к df. Затем происходит какая-то длинная и широкая хитрость. Не стесняйтесь изучать каждый шаг в отдельности.

library(tidyr)

df <- data.frame(id = 411:420,
                 value = c(10,0,25,0,32,66,45,88,0,23),
                 prod =  c(500,300,400,600,0,800,400,300,200,0)
)

add_coll <- function(x) {

  if (x["value"] >0  & x["prod"] > 0) {

    varname_v <- paste0("col_",x["id"],"_v")
    varname_p <- paste0("col_",x["id"],"_p")

    return(data.frame(varname_v, varname_p))
  } else {
    return(data.frame(varname_v = NA, varname_p = NA))
  }
}

out <- apply(df, MARGIN = 1, FUN = add_coll)
out <- do.call(rbind, out)

xy <- cbind(df, out)

xywide <- pivot_wider(xy, names_from = varname_v, values_from = value)
xywide <- xywide[, colnames(xywide) != "NA"]
xywide <- pivot_wider(xywide, names_from = varname_p, values_from = prod)
xywide <- xywide[, colnames(xywide) != "NA"]
xywide[is.na(xywide)] <- 0

res <- merge(df, xywide)
res

    id value prod col_411_v col_413_v col_416_v col_417_v col_418_v col_411_p col_413_p col_416_p
1  411    10  500        10         0         0         0         0       500         0         0
2  412     0  300         0         0         0         0         0         0         0         0
3  413    25  400         0        25         0         0         0         0       400         0
4  414     0  600         0         0         0         0         0         0         0         0
5  415    32    0         0         0         0         0         0         0         0         0
6  416    66  800         0         0        66         0         0         0         0       800
7  417    45  400         0         0         0        45         0         0         0         0
8  418    88  300         0         0         0         0        88         0         0         0
9  419     0  200         0         0         0         0         0         0         0         0
10 420    23    0         0         0         0         0         0         0         0         0
   col_417_p col_418_p
1          0         0
2          0         0
3          0         0
4          0         0
5          0         0
6          0         0
7        400         0
8          0       300
9          0         0
10         0         0

Если бы вы выбрали go for l oop, это был бы один из способов сделать это. По сути, создаем ghost data.frame со всеми нулями, а затем заполняем данные, если строка соответствует вашим критериям. Преимущество этого метода в том, что он очень расширяемый. Но он использует cbind способом, который может быть неэффективным для довольно больших наборов данных.

for (i in seq_len(nrow(df))) {
  myrow <- df[i, ]

  temp.cols <- dummy.template
  colnames(temp.cols) <- c(
    paste0("col_", myrow$id, "_v"),
    paste0("col_", myrow$id, "_p")
  )

  if (myrow$value > 0 & myrow$prod > 0) {
    temp.cols[i, 1] <- myrow$value
    temp.cols[i, 2] <- myrow$prod

    df <- cbind(df, temp.cols)
  }
}

    id value prod col_411_v col_411_p col_413_v col_413_p col_416_v
1  411    10  500        10       500         0         0         0
2  412     0  300         0         0         0         0         0
3  413    25  400         0         0        25       400         0
4  414     0  600         0         0         0         0         0
5  415    32    0         0         0         0         0         0
6  416    66  800         0         0         0         0        66
7  417    45  400         0         0         0         0         0
8  418    88  300         0         0         0         0         0
9  419     0  200         0         0         0         0         0
10 420    23    0         0         0         0         0         0
   col_416_p col_417_v col_417_p col_418_v col_418_p
1          0         0         0         0         0
2          0         0         0         0         0
3          0         0         0         0         0
4          0         0         0         0         0
5          0         0         0         0         0
6        800         0         0         0         0
7          0        45       400         0         0
8          0         0         0        88       300
9          0         0         0         0         0
10         0         0         0         0         0
...