基于R数据帧中特定的行、行值和列组的新变量的条件计算

问题描述 投票:0回答:2

示例数据

我在 R 中获得了以下调查数据集,并且需要有关特定新变量的条件计算的帮助。

# Load package
library(tidyverse)

# Important: set seed for replicability
set.seed(123)

# Create data: step 1
df <- tibble(
  country = c(rep("A", 10), rep("B", 10)),
  respondent_id = 1:20,
  vote_choice = c(sample(c("PartyA", "PartyB", "PartyC"), 10, replace = TRUE),
                  sample(c("PartyD", "PartyE", "PartyF"), 10, replace = TRUE)),
  ptv_1 = runif(20, min = 0, max = 1) %>% round(., 3),
  ptv_2 = runif(20, min = 0, max = 1) %>% round(., 3),
  ptv_3 = runif(20, min = 0, max = 1) %>% round(., 3)
)

# Create data: step 2
df <- df %>% 
  group_by(vote_choice, country) %>%
  summarize(across(starts_with("ptv"), \(x) mean(x, na.rm = TRUE))) %>%
  pivot_longer(cols = starts_with("ptv"), names_to = "party_to_ptv", values_to = "average_value") %>%
  group_by(vote_choice, country) %>%
  slice_max(order_by = average_value) %>%
  ungroup() %>%
  mutate(average_value = NULL) %>%
  right_join(., df, by = c("vote_choice", "country"))

# Inspect data
df

# A tibble: 20 × 7
   vote_choice country party_to_ptv respondent_id ptv_1 ptv_2 ptv_3
   <chr>       <chr>   <chr>                <int> <dbl> <dbl> <dbl>
 1 PartyA      A       ptv_2                   10 0.691 0.799 0.710 
 2 PartyB      A       ptv_3                    4 0.544 0.233 0.810 
 3 PartyB      A       ptv_3                    6 0.289 0.266 0.794
 4 PartyB      A       ptv_3                    7 0.147 0.858 0.440 
 5 PartyB      A       ptv_3                    8 0.963 0.046 0.754
 6 PartyC      A       ptv_1                    1 0.994 0.369 0.274
 7 PartyC      A       ptv_1                    2 0.656 0.152 0.815
 8 PartyC      A       ptv_1                    3 0.709 0.139 0.449
 9 PartyC      A       ptv_1                    5 0.594 0.466 0.812
10 PartyC      A       ptv_1                    9 0.902 0.442 0.629
11 PartyD      B       ptv_3                   13 0.478 0.207 0.220 
12 PartyD      B       ptv_3                   16 0.318 0.895 0.352
13 PartyD      B       ptv_3                   19 0.415 0.095 0.668
14 PartyD      B       ptv_3                   20 0.414 0.384 0.418
15 PartyE      B       ptv_1                   11 0.795 0.122 0.001
16 PartyE      B       ptv_1                   12 0.025 0.561 0.475
17 PartyE      B       ptv_1                   14 0.758 0.128 0.380 
18 PartyF      B       ptv_2                   15 0.216 0.753 0.613
19 PartyF      B       ptv_2                   17 0.232 0.374 0.111
20 PartyF      B       ptv_2                   18 0.143 0.665 0.244

变量信息:

  • country
    在我的示例 df 中包含 2 个国家,每个国家包含 10 个受访者和受访者在上次选举中必须选择的一组 3 个不同政党(真实数据还包含一个变量
    year
    ,我没有将其包含在内)为了简单起见)
  • respondent_id
    指的是调查数据集中的受访者,表明该数据集处于受访者级别,但可以忽略不计
  • vote_choice
    表示受访者在上次选举中投票支持的政党的名称
  • ptv_1
    ptv_2
    ptv_3
    表示每个可用政党的每个受访者对该政党的倾向(在真实数据中,受访者当然更倾向于他们投票支持的政党);规模:
    0-1
  • party_to_ptv
    是一个转换列表,表示
    vote_choice
    中的哪一方对应于哪
    ptv_*

问题描述

我现在需要计算一组 (3) 个名为

electoral_opportunites_*
的新变量,其中星号是 1-3 的占位符,指的是三个 PTV。这个想法是根据其他政党选民的有利倾向来计算政党获得新选民的变化。

为此,我需要计算:

1 - (sqrt(PTV of party voted for) - sqrt(PTV of other party))
,其想法是设定自己政党相对于新政党的支持力度。例如,如果受访者通过 PTV = 1.0 强烈支持自己的政党 A,那么他们通过 PTV = 0.4 也倾向于 B 并不那么重要。

我的计算问题是条件性:我需要按行查找每个受访者与其选择方对应的 PTV 列值(可能不是行中最高的 PTV 值),然后从中减去平方-另一列的根值。

对于示例 df,我会手动执行以下操作。

预期结果(

electoral_opportunities_1

df %>% 
  mutate(electoral_potential_1 = 
           # Subtract: PTV (party voted for) - PTV (PTV column 1)...
           c(1 - ( sqrt(0.799) - sqrt(0.691) ),
             1 - ( sqrt(0.810) - sqrt(0.544) ),
             1 - ( sqrt(0.794) - sqrt(0.289) ),
             1 - ( sqrt(0.440) - sqrt(0.147) ),
             1 - ( sqrt(0.754) - sqrt(0.963) ),
             NA, # ...unless they are both the same.
             NA,
             NA,
             NA,
             NA,
             1 - ( sqrt(0.220) - sqrt(0.478) ),
             1 - ( sqrt(0.352) - sqrt(0.318) ),
             1 - ( sqrt(0.668) - sqrt(0.415) ),
             1 - ( sqrt(0.418) - sqrt(0.414) ),
             NA,
             NA,
             NA,
             1 - ( sqrt(0.753) - sqrt(0.216) ),
             1 - ( sqrt(0.374) - sqrt(0.232) ),
             1 - ( sqrt(0.665) - sqrt(0.143) )) ) -> df

df

作为一个小细节,我随后会检查是否有任何值 > 1 并将其上限为 1,这意味着如果受访者更强烈地倾向于他们实际上并未投票支持的政党,则该政党将获得最高分( 1) 在其选举变更方面以争取该选民。

df %>% 
  mutate(electoral_opportunities_1 = ifelse(electoral_opportunities_1 > 1, 1, electoral_opportunities_1)) -> df

我无法手工完成所有这些工作。因此,如果有一个高效、整洁的解决方案来计算各个 PTV 专栏的选举机会,我将不胜感激。我尝试了许多不同的方法,包括旋转 df,但到目前为止都没有奏效。综合起来,流程是:

  • 取vote_choice对应的PTV列的值。
  • 从此值中减去给定 PTV 列的值即可计算该政党的选举机会。
  • 除非双方相同,在这种情况下将值设置为 NA。
  • 然后,检查是否有任何值 > 1 并将其限制为 1。

编辑

我刚刚注意到,在最终的 df 中,我当然需要 vote_choice 中每个政党的平均选举机会,而不是三个单独的列!

r conditional-statements pivot mutate
2个回答
1
投票

这个解决方案看起来有点麻烦,但如果我正确理解你的问题,它应该可以工作:

library(tidyverse) 

df %>%
  pivot_longer(cols = starts_with("ptv"), 
               names_to = "ptv", 
               values_to = "ptv_value") %>%
  group_by(respondent_id) %>%
  mutate(voted_party_ptv = ptv_value[party_to_ptv == ptv]) %>%
  ungroup() %>%
  mutate(electoral_opportunity = ifelse(party_to_ptv != ptv, 
                                        pmin(1, 1 - (sqrt(voted_party_ptv) - sqrt(ptv_value))), 
                                        NA)) %>% 
  select(-c(voted_party_ptv, ptv_value)) %>%
  pivot_wider(names_from = ptv, 
              values_from = electoral_opportunity, 
              names_prefix = "electoral_opportunity_") %>%
  mutate(avg_electoral_opportunity = rowMeans(select(., starts_with("electoral_opportunity")), na.rm = TRUE))

给出:

vote_choice country party_to_ptv respondent_id electoral_opportunity_ptv_1 electoral_opportunity_ptv_2 electoral_opportunity_pt…¹ avg_e…²
   <chr>       <chr>   <chr>                <int>                       <dbl>                       <dbl>                      <dbl>   <dbl>
 1 PartyA      A       ptv_2                   10                       0.937                      NA                          0.949   0.943
 2 PartyB      A       ptv_3                    4                       0.838                       0.583                     NA       0.710
 3 PartyB      A       ptv_3                    6                       0.647                       0.625                     NA       0.636
 4 PartyB      A       ptv_3                    7                       0.720                       1                         NA       0.860
 5 PartyB      A       ptv_3                    8                       1                           0.346                     NA       0.673
 6 PartyC      A       ptv_1                    1                      NA                           0.610                      0.526   0.568
 7 PartyC      A       ptv_1                    2                      NA                           0.580                      1       0.790
 8 PartyC      A       ptv_1                    3                      NA                           0.531                      0.828   0.679
 9 PartyC      A       ptv_1                    5                      NA                           0.912                      1       0.956
10 PartyC      A       ptv_1                    9                      NA                           0.715                      0.843   0.779
11 PartyD      B       ptv_3                   13                       1                           0.986                     NA       0.993
12 PartyD      B       ptv_3                   16                       0.971                       1                         NA       0.985
13 PartyD      B       ptv_3                   19                       0.827                       0.491                     NA       0.659
14 PartyD      B       ptv_3                   20                       0.997                       0.973                     NA       0.985
15 PartyE      B       ptv_1                   11                      NA                           0.458                      0.140   0.299
16 PartyE      B       ptv_1                   12                      NA                           1                          1       1    
17 PartyE      B       ptv_1                   14                      NA                           0.487                      0.746   0.616
18 PartyF      B       ptv_2                   15                       0.597                      NA                          0.915   0.756
19 PartyF      B       ptv_2                   17                       0.870                      NA                          0.722   0.796
20 PartyF      B       ptv_2                   18                       0.563                      NA                          0.678   0.621

您可以省略任何不需要的列


0
投票

好吧,这显然比我最初想象的更直接。这是我为解决(80%)问题所做的工作。

df %>% 
  mutate(ptv_v = case_when(party_to_ptv == "ptv_1" ~ ptv_1,
                           party_to_ptv == "ptv_2" ~ ptv_2,
                           party_to_ptv == "ptv_3" ~ ptv_3,
                           T ~ NA_real_)) %>% 
  mutate(opportunity_1 = ifelse(ptv_1 > ptv_v, 1, 1 - (sqrt(ptv_v) - sqrt(ptv_1)) ) %>% ifelse(party_to_ptv == "ptv_1", NA, .)),
         opportunity_1 = ifelse(party_to_ptv == "ptv_1") ) -> df

现在我只需要在 vote_choice 中获取每个政党的平均选举机会即可。 :)

© www.soinside.com 2019 - 2024. All rights reserved.