Создать новый столбец, равный одному из многих существующих столбцов при выполнении условия - PullRequest
1 голос
/ 05 мая 2019

У меня широкий массив данных с результатами выборов.Мне нужно сделать новую колонку, в которой говорится, сколько голосов получила конкретная партия.То, как записываются голоса, означает, что для этого мне нужно перебрать большое количество столбцов.Я вижу, как это сделать с помощью цикла for, но я бы хотел, чтобы он работал, используя purrr.

Вот пример того, как выглядят данные:

df <- data.frame(district = c("A", "B"),
                 party1 = c("Lab", "Con"), 
                 votes1 = c(188, 200),
                 party2 = c("LD", "Lab"),
                 votes2 = c(140, 164),
                 party3 = c("Con", "LD"),
                 votes3 = c(23, 99))

Я хочу создать новый столбец, записывающий, сколько голосов получила партия «LD».Таким образом, в этом примере это будет:

df$LD_votes <- c(140,99)

Я связал это, но безуспешно:

df <- df %>% map(1:34, function(x) mutate(LD_votes = ifelse(paste0(party, x)=="LD", paste0(votes, x), NA)))

Как я могу заставить код работать по этим строкам?

Ответы [ 4 ]

1 голос
/ 06 мая 2019

Здесь у меня есть решение data.table.Сначала мы конвертируем df в data.table:

library(data.table)
df <- data.frame(district = c("A", "B"),
                 party1 = c("Lab", "Con"), 
                 votes1 = c(188, 200),
                 party2 = c("LD", "Lab"),
                 votes2 = c(140, 164),
                 party3 = c("Con", "LD"),
                 votes3 = c(23, 99))
setDT(df)# converting to data.table

Затем я конвертирую df из широкой в ​​длинную форму x, чтобы мы могли суммировать 'голоса' согласно 'району' и 'партии'

x <- melt(df,id.vars = "district",  # Melting data to long
     measure.vars = patterns("^party", "^votes"),
     value.name = c("party", "votes"))

Что возвращает

#Displaying x
x
   district variable party votes
1:        A        1   Lab   188
2:        B        1   Con   200
3:        A        2    LD   140
4:        B        2   Lab   164
5:        A        3   Con    23
6:        B        3    LD    99

Теперь я вычисляю y - сумму в соответствии с районом и партией и фильтрую только требуемую партию "LD".

y <- x[party=="LD", .(SumV=sum(votes)), .(district, party)]

Наконец, я добавляю к столбцу SumV с y до df.Я сортирую y в соответствии с district, чтобы избежать присвоения сумм LD различным округам.

df[ , LD_votes:= y[order(district),SumV]]
df
   district party1 votes1 party2 votes2 party3 votes3 LD_votes
1:        A    Lab    188     LD    140    Con     23      140
2:        B    Con    200    Lab    164     LD     99       99

Аналогично вечеринкам Con и Lab

y <- x[party=="Lab", .(SumV=sum(votes)), .(district, party)]
df[ , Lab_votes:= y[order(district),SumV]]
y <- x[party=="Con", .(SumV=sum(votes)), .(district, party)]
df[ , Con_votes:= y[order(district),SumV]]
df
   district party1 votes1 party2 votes2 party3 votes3 LD_votes Lab_votes Con_votes
1:        A    Lab    188     LD    140    Con     23      140       188        23
2:        B    Con    200    Lab    164     LD     99       99       164       200
0 голосов
/ 06 мая 2019

Это может быть лучше встроено, но это работает.

library(tidyverse)

df <- data.frame(district = c("A", "B"),
                 party1 = c("Lab", "Con"),
                 votes1 = c(188, 200),
                 party2 = c("LD", "Lab"),
                 votes2 = c(140, 164),
                 party3 = c("Con", "LD"),
                 votes3 = c(23, 99))

party <- df %>%
    select(district, starts_with("party")) %>%
    gather(key="col", value="party", starts_with("party"))
votes <- df %>%
    select(district, starts_with("votes")) %>%
    gather(key="col", value="votes", starts_with("votes"))
result <- party %>%
    select(-col) %>% 
    mutate(votes=votes$votes) %>% 
    group_by(party, district) %>% 
    summarise(total=sum(votes))

> result
  party district total
1 Con   A           23
2 Con   B          200
3 Lab   A          188
4 Lab   B          164
5 LD    A          140
6 LD    B           99
0 голосов
/ 06 мая 2019

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

library(tidyverse)
df1 <- df %>%
  rowid_to_column(var = "orig_row") %>%
  gather(col, val, -c(orig_row, district)) %>%
  arrange(orig_row) %>%
  group_by(orig_row) %>%
  mutate(grp_num = (1 + row_number()) %/% 2,
         col = str_remove(col, "[0-9]")) %>%
  ungroup() %>%
  spread(col, val) %>%
  mutate(votes = parse_number(votes))

df1 %>% count(party, district, wt = votes)
0 голосов
/ 05 мая 2019

Используйте это

df <- df %>% 
  mutate("LDVotes" = (ifelse(party1 == "LD", votes1, 0) + ifelse(party2 == "LD", votes2, 0) + ifelse(party3 == "LD", votes3, 0)),
         "LabVotes" = (ifelse(party1 == "Lab", votes1, 0) + ifelse(party2 == "Lab", votes2, 0) + ifelse(party3 == "Lab", votes3, 0)),
         "ConVotes" = (ifelse(party1 == "Con", votes1, 0) + ifelse(party2 == "Con", votes2, 0) + ifelse(party3 == "Con", votes3, 0)))
...