R: столбцы заголовка df являются порядковым ранжированием и распределены по столбцам для каждого наблюдения - PullRequest
0 голосов
/ 05 июля 2018

У меня есть данные анкеты, которые выглядят следующим образом:

   items no_stars1  no_stars2   no_stars3   average satisfied   bad
1     A         1           0           0         0         0     1
2     B         0           1           0         1         0     0
3     C         0           0           1         0         1     0
4     D         0           1           0         0         1     0
5     E         0           0           1         1         0     0
6     F         0           0           1         0         1     0
7     G         1           0           0         0         0     1

По сути, столбцы заголовка (количество звездочек и удовлетворительное) являются порядковыми номерами для каждого элемента. Я хотел бы суммировать no_stars (столбец 2: 4) и удовлетворительно (столбец 5: 7) в один столбец, чтобы результат выглядел так:

   items    no_stars    satisfactory    
1     A         1           1           
2     B         2           2           
3     C         3           3           
4     D         2           3           
5     E         3           2           
6     F         3           3           
7     G         1           1         

$ no_stars <- 1 для no_stars1, 2 для no_stars2, 3 для no_stars3 </p>

$ удовлетворительно <- 1 для плохого, 2 для среднего, 3 для хорошего </p>

Я попробовал код ниже

df$no_stars2[df$no_stars2 == 1] <- 2
df$no_stars3[df$no_stars3 == 1] <- 3

df$average[df$average == 1] <- 2
df$satisfied[df$satisfied == 1] <- 3

no_stars <- df$no_stars1 + df$no_stars2 + df$no_stars3
satisfactory <- df$bad + df$average + df$satisfied

tidy_df <- data.frame(df$Items, no_stars, satisfactory)
tidy_df

Есть ли в R функция, которая может делать то же самое? или же кто-нибудь получил лучшее и более простое решение?

Спасибо

Ответы [ 5 ]

0 голосов
/ 05 июля 2018

с использованием apply и match:

data.frame(
  items        = df1$items,
  no_stars     = apply(df1[2:4], 1, match, x=1),
  satisfactory = apply(df1[c(7,5:6)], 1, match, x=1))

#   items no_stars satisfactory
# 1     A        1            1
# 2     B        2            2
# 3     C        3            3
# 4     D        2            3
# 5     E        3            2
# 6     F        3            3
# 7     G        1            1

данные

df1 <- read.table(header=TRUE,stringsAsFactors=FALSE,text="
   items no_stars1  no_stars2   no_stars3   average satisfied   bad
1     A         1           0           0         0         0     1
2     B         0           1           0         1         0     0
3     C         0           0           1         0         1     0
4     D         0           1           0         0         1     0
5     E         0           0           1         1         0     0
6     F         0           0           1         0         1     0
7     G         1           0           0         0         0     1")
0 голосов
/ 05 июля 2018
dat%>%
   replace(.==1,NA)%>%
   replace_na(setNames(as.list(names(.)),names(.)))%>%
   replace(.==0,NA)%>%
   mutate(s=coalesce(!!!.[2:4]),
          no_stars=as.numeric(factor(s,unique(s))),
          t=coalesce(!!!.[5:7]),
          satisfactory=as.numeric(factor(t,unique(t))))%>%
   select(items,no_stars,satisfactory)

  items no_stars satisfactory
1     A        1            1
2     B        2            2
3     C        3            3
4     D        2            3
5     E        3            2
6     F        3            3
7     G        1            1
0 голосов
/ 05 июля 2018

Просто используйте max.col и установите предпочтения:

starsOrder<-c("no_stars1","no_stars2","no_stars3")
satOrder<-c("bad","average","satisfied")
data.frame(items=df$items,no_stars=max.col(df[,starsOrder]),
            satisfactory=max.col(df[,satOrder]))
#  items no_stars satisfactory
#1     A        1            1
#2     B        2            2
#3     C        3            3
#4     D        2            3
#5     E        3            2
#6     F        3            3
#7     G        1            1
0 голосов
/ 05 июля 2018

Другое решение tidyverse, использующее преобразования factor в integer для кодирования no_stars и satisfactory и расширение от широкого до длинного дважды:

library(tidyverse)
df %>%
    gather(no_stars, v1, starts_with("no_stars")) %>%
    mutate(no_stars = as.integer(factor(no_stars))) %>%
    gather(satisfactory, v2, average, satisfied, bad) %>%
    filter(v1 > 0 & v2 > 0) %>%
    mutate(satisfactory = as.integer(factor(
        satisfactory, levels = c("bad", "average", "satisfied")))) %>%
    select(-v1, -v2) %>%
    arrange(items)
#  items no_stars satisfactory
#1     A        1            1
#2     B        2            2
#3     C        3            3
#4     D        2            3
#5     E        3            2
#6     F        3            3
#7     G        1            1
0 голосов
/ 05 июля 2018

Несмотря на то, что могут быть более элегантные решения, использование dplyr::case_when() дает вам гибкость для кодирования вещей так, как вы хотите:

library(dplyr)

df %>% 
  dplyr::mutate(
    no_stars = dplyr::case_when(
      no_stars1 == 1 ~ 1,
      no_stars2 == 1 ~ 2,
      no_stars3 == 1 ~ 3)
    , satisfactory = dplyr::case_when(
      average   == 1 ~ 2,
      satisfied == 1 ~ 3,
      bad       == 1 ~ 1)
  )
# items no_stars1 no_stars2 no_stars3 average satisfied bad no_stars satisfactory
# 1     A         1         0         0       0         0   1        1            1
# 2     B         0         1         0       1         0   0        2            2
# 3     C         0         0         1       0         1   0        3            3
# 4     D         0         1         0       0         1   0        2            3
# 5     E         0         0         1       1         0   0        3            2
# 6     F         0         0         1       0         1   0        3            3
# 7     G         1         0         0       0         0   1        1            1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...