Написание функции, которая воспроизводит тот же вывод, что и «отдельная» функция dplyr в R - PullRequest
1 голос
/ 18 марта 2020

Я делаю упражнение, чтобы попрактиковаться в написании функций. Проблема в том, чтобы моя функция воспроизводила тот же вывод, что и функция separate в dplyr.

У меня есть следующий фрейм данных:

df <- data.frame(dates = c("2005-06-29", "2005-07-16", "2005-12-01"), 
                  values = c("F:62:130", "F:68:149", "M:68:160"),
                  stringsAsFactors = FALSE)

Я хочу разделить столбец «значения» на три отдельных столбца (разделить на двоеточие) и удалить столбец «значения» в окончательный фрейм данных должен выглядеть следующим образом:

dates        gender  ht   wt
1 2005-06-29      F  62  130
2 2005-07-16      F  68  149
3 2005-12-01      M  68  160

Проблема, с которой я сталкиваюсь, заключается в присвоении имен новым столбцам в моей функции. Это то, что у меня есть:


  into <- c() 
  names(into) <- c(a = "", b = "", c = "") 

Но когда я запускаю свою новую функцию, я получаю сообщение об ошибке, которое пытаюсь to set an attribute on NULL.

Когда я удаляю в / names (into), я получаю следующее (с неправильными именами новых столбцов):

dates            values   a  b   c
1 2005-06-29   F:62:130   F 62  130
2 2005-07-16   F:68:149   F 68  149
3 2005-12-01   M:68:160   F 68  160

Как создать аргумент into в функции, который позволяет мне называть столбцы так, как я хочу

Ответы [ 2 ]

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

В base R мы можем использовать substring

transform(df, a = substr(values, 1, 1), 
         b = substring(values, 3, 4),
          wt = substring(values, 6))

Или другой более простой вариант - прочитать с read.table, указав sep как :, и создать столбцы на исходный набор данных по назначению или cbind ing

df[c('a', 'b', 'wt')] <- read.table(text = df$values,  sep=":",  header = FALSE)
df
#       dates   values a  b  wt
#1 2005-06-29 F:62:130 F 62 130
#2 2005-07-16 F:68:149 F 68 149
#3 2005-12-01 M:68:160 M 68 160

Функцию OP можно изменить на

myfunc <- function(df, colnum = 2, into = c("a", "b", "c"), sep = ":") {

  # Use "colnum" to access the specified column of "df"
  j1 <- colnum
  colnum <- df[ , colnum]

  # Split "df" using the specified separator 
  storage <- strsplit(colnum, split = sep)


  # Take/second/third elements and store it into the above vectors
  a <- sapply(storage, function(x) x[1])
  b <- sapply(storage, function(x) x[2])
  c <- sapply(storage, function(x) x[3])

  out <- cbind(df, setNames(list(a, b, c), into))
  out[setdiff(names(out), names(df)[j1])]

}

myfunc(df)
#.       dates a  b   c
#1 2005-06-29 F 62 130
#2 2005-07-16 F 68 149
#3 2005-12-01 M 68 160



myfunc(df, into = c('a1', 'b1', 'c1'))
#      dates a1 b1  c1
#1 2005-06-29  F 62 130
#2 2005-07-16  F 68 149
#3 2005-12-01  M 68 160
0 голосов
/ 18 марта 2020

Вот базовое решение R

dfout <- cbind(df,`colnames<-`(do.call(rbind,strsplit(df$values,":")),c("a","b","wt")))

, которое дает

> dfout
       dates   values a  b  wt
1 2005-06-29 F:62:130 F 62 130
2 2005-07-16 F:68:149 F 68 149
3 2005-12-01 M:68:160 M 68 160
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...