我如何创建许多变量,这些变量取决于R中的多个条件(类似于SAS中的数组函数)



我正在分析一个时间使用数据集,其中对于每个家庭成员,144列表示他们在每10分钟(即从08:00到08:10(进行的活动,144列指示伴侣是否在每个时间间隔出现,依此类推

我试图创建两种不同类型的变量。

  1. 我需要总结一个人在有和没有伴侣的情况下在某些活动中花费的时间(例如,一个用于谈话和吃饭的总和变量、一个用于休闲的总和变量(

在SAS中,这与以下阵列的使用有关:

array main_men(*) main_men_1-main_men_144;
array partner_men(*) partner_men_1-partner_men_144;
sum_eating = 0;
do i=1 to 144; if main_men(i) in (100:200) & partner_men(i) in (0) 
then sum_eating = sum_eating + 10; end;

因此,每次出现特定活动代码和伙伴在同一变量槽(1至144(中存在的条件都得到满足,增加了一个新变量+10分钟(因为每次出现代表一个10分钟的时隙(。在R中,计数两个条件都满足的情况就足够了。

  1. 为了进行序列分析,我不仅需要和变量,还需要144个新变量,这些变量表明个人是独自休闲还是与伴侣一起休闲,或者正在做无偿工作等

所以我需要144个变量用于24。同样,我只知道SAS的逻辑,但我想彻底放弃SAS,转而使用R.

array seq(*) seq_1-seq_144;
do i=1 to 144; if main_men(i) in (200:399) and partner_men(i) in (0) 
then seq_paar(i)=1; end; 
do i=1 to 144; if main_men(i) in (200:399) and partner_men(i) in (1) 
then seq_paar(i)=2; end; 

在这里,我创建了144个空白变量,如果发生了特定的活动代码,并且个人是单独的(partner_men为0(,则为1;如果发生了代码,但个人与伴侣在一起,则为0。

我创建了一个数据集的小样本,希望它能更加清晰和可复制:

structure(list(id = c(11, 12, 17, 31, 35, 36, 41, 42, 47, 61), 
men_main_55 = c(210, 210, 421, 992, 132, 622, 630, 466, 611, 
969), men_main_56 = c(210, 210, 421, 992, 132, 622, 630, 
466, 611, 969), men_main_57 = c(210, 210, 421, 992, 611, 
622, 630, 466, 611, 969), men_main_58 = c(210, 210, 421, 
131, 120, 622, 466, 466, 611, 641), men_main_59 = c(210, 
210, 421, 452, 120, 622, 466, 466, 611, 641), men_main_60 = c(210, 
210, 421, 452, 120, 622, 466, 466, 611, 641), wom_main_55 = c(210, 
210, 421, 992, 411, 622, 421, 120, 641, 630), wom_main_56 = c(210, 
210, 421, 992, 411, 622, 947, 120, 641, 630), wom_main_57 = c(210, 
210, 421, 992, 611, 622, 947, 120, 641, 630), wom_main_58 = c(210, 
210, 421, 998, 120, 622, 947, 421, 641, 630), wom_main_59 = c(210, 
210, 421, 461, 120, 622, 421, 421, 641, 630), wom_main_60 = c(210, 
210, 421, 461, 120, 622, 421, 421, 641, 630), partner_men_55 = c(0, 
0, 1, 1, 0, 1, 0, 0, 1, 0), partner_men_56 = c(0, 0, 1, 1, 
0, 1, 0, 0, 1, 0), partner_men_57 = c(0, 0, 1, 1, 1, 1, 0, 
0, 1, 0), partner_men_58 = c(0, 0, 1, 0, 1, 1, 0, 0, 1, 1
), partner_men_59 = c(0, 0, 1, 0, 1, 1, 0, 0, 1, 1), partner_men_60 = c(0, 
0, 1, 0, 1, 1, 0, 0, 1, 1), partner_wom_55 = c(0, 0, 1, 1, 
0, 1, 0, 0, 1, 0), partner_wom_56 = c(0, 0, 1, 1, 0, 1, 0, 
0, 1, 0), partner_wom_57 = c(0, 0, 1, 1, 1, 1, 0, 0, 1, 0
), partner_wom_58 = c(0, 0, 1, 0, 1, 1, 0, 0, 1, 0), partner_wom_59 = c(0, 
0, 1, 0, 1, 1, 0, 0, 1, 0), partner_wom_60 = c(0, 0, 1, 0, 
1, 1, 0, 0, 1, 0)), row.names = c(NA, -10L), label = "PAARZEIT_SEQ", 
class = c("tbl_df", "tbl", "data.frame"))

如有任何帮助,我们将不胜感激。我尝试了各种应用循环方法,但都不起作用。谢谢

您的示例数据与您的示例代码不一致(请检查列名(,并且您没有给我们任何预期的输出,因此很难确定您想要什么。

SAS和R对数据集/数据帧的看法之间的根本区别在于,SAS将数据视为的集合,而R将数据视为由组成的集合:他们对世界的看法相互垂直。因此,通过简单地将SAS代码翻译成R,你会让自己的生活变得困难。在你的第二个问题中,困难尤为明显。如果你在从SAS到R的过程中将世界观从行转移到列,从长远来看,你会省去很多痛苦和精力。

[顺便说一句,在一个帖子上问两个问题是不好的。]

采用整洁的数据实践也将是有益的,无论你是在SAS还是R工作:这些原则都是通用的。

也就是说,为了回答你的第一个问题:

library(tidyverse)
df %>% 
rowwise() %>% 
mutate(
sumEatingMen=10*rowSums(across(starts_with("men_main_"), ~. %in% 100:200)),
sumEatingWom=10*rowSums(across(starts_with("wom_main_"), ~. %in% 100:200))
) %>% 
ungroup() %>% 
select(id, sumEatingMen, sumEatingWom)
# A tibble: 10 x 3
id sumEatingMen sumEatingWom
<dbl>        <dbl>        <dbl>
1    11            0            0
2    12            0            0
3    17            0            0
4    31           10            0
5    35           50           30
6    36            0            0
7    41            0            0
8    42            0           30
9    47            0            0
10    61            0            0

要以类似R的方式回答问题,首先将数据转换为整洁的格式:

df1a <- df %>% 
pivot_longer(
cols=c(starts_with("men"), starts_with("wom")),
names_pattern="(.*)_main_(.*)",
values_to="Activity",
names_to=c("Sex", "Index")
) %>% 
select(id, Sex, Index, Activity)
df1b <- df %>% 
pivot_longer(
cols=c(starts_with("partner")),
names_pattern="partner_(.*)_(.*)",
values_to="Partner",
names_to=c("Sex", "Index")
) %>% 
select(id, Sex, Index, Partner)
df1 <- df1a %>% full_join(df1b, by=c("id", "Sex", "Index"))
df1
# A tibble: 120 x 5
id Sex   Index Activity Partner
<dbl> <chr> <chr>    <dbl>   <dbl>
1    11 men   55         210       0
2    11 men   56         210       0
3    11 men   57         210       0
4    11 men   58         210       0
5    11 men   59         210       0
6    11 men   60         210       0
7    11 wom   55         210       0
8    11 wom   56         210       0
9    11 wom   57         210       0
10    11 wom   58         210       0
# … with 110 more rows

你的问题的答案是

df1 %>% 
group_by(id, Sex) %>% 
summarise(sumEating=10*sum(Activity %in% 100:200), .groups="drop")
# A tibble: 20 x 3
id Sex   sumEating
* <dbl> <chr>     <dbl>
1    11 men           0
2    11 wom           0
3    12 men           0
4    12 wom           0
5    17 men           0
6    17 wom           0
7    31 men          10
8    31 wom           0
9    35 men          50
10    35 wom          30
<10 rows omitted>

请注意,与类似SAS的解决方案相比,此解决方案更加通用、紧凑和可读。

以整洁的方式回答您的第二个问题:

df1 %>%
mutate(unpaidWorkWithPartner=Activity %in% 200:399 & Partner == 1)
# A tibble: 120 x 6
id Sex   Index Activity Partner unpaidWorkWithPartner
<dbl> <chr> <chr>    <dbl>   <dbl> <lgl>                
1    11 men   55         210       0 FALSE                
2    11 men   56         210       0 FALSE                
3    11 men   57         210       0 FALSE                
4    11 men   58         210       0 FALSE                
5    11 men   59         210       0 FALSE                
6    11 men   60         210       0 FALSE                
7    11 wom   55         210       0 FALSE                
8    11 wom   56         210       0 FALSE                
9    11 wom   57         210       0 FALSE                
10    11 wom   58         210       0 FALSE                
# … with 110 more rows

如果我正确理解你的帖子,在你的样本数据集中,没有人在任何时候与他们的伴侣一起做任何无偿工作。

可以用类似SAS的方式回答你的第二个问题,但我怀疑解决方案会很长、很脆弱、很尴尬。我当然没有时间进一步调查。

相关内容

  • 没有找到相关文章

最新更新