将字符串用于dplyr过滤器和循环

时间:2018-08-12 15:46:04

标签: r for-loop

我有一个数据集,其中包含一个Person ID(个人)列表,每个人使用的某些语言功能以及每个人使用了多少次。看起来像这样:

df <- data.frame(PID = c(1, 1, 2, 2, 2, 3, 3), Feature = c("F2", "F3", "F1", "F2", "F3", "F1", "F3"), Freq = c(2, 1, 3, 1, 2, 4, 3))

ids <- data.frame(PID = 1:3, Level = c("low", "mid", "high"))

我正在将其转换为一个数据行,该数据行每行一个人,语言特征作为列:

f_freq <- data.frame(ids[1:2], matrix(nrow = nrow(ids), ncol = 3))
f_names <- c("F1", "F2", "F3) 
names(f_freq)[3:5] <- f_names 

所以我想将频率信息从第一个数据帧(df)映射到新的(f_freq),并为每个个人未使用的功能插入0。我写了一个for循环来达到这个目的:

for (h in 1:length(f_names)) {
    for (j in 1:nrow(f_freq)) {
        t1 <- filter(df, Feature == f_names[[h]])
        if (f_freq$PID[j] %in% t1$PID) {
            f_freq[j, f_names[[h]]] <- t1[t1$PID == f_freq$ID[j], "Freq"]
        } else {
            out[j, f_names[[h]]] <- 0
        }
    }
}

但是它只返回NA。当我输入每个功能名称时,它会起作用,如下所示。

for (h in 1:length(f_names)) {
    for (j in 1:nrow(f_freq)) {
        t1 <- filter(df, Feature == "F1")
        if (f_freq$PID[j] %in% t1$PID) {
            f_freq[j, "F1"] <- t1[t1$PID == f_freq$ID[j], "Freq"]
        } else {
            out[j, "F1"] <- 0
        }
    }
}

但是我在实际数据中有35个功能,因此我想使它自动化。我不确定为什么第一个循环不起作用。如果有人知道如何解决此问题,请告诉我!!

1 个答案:

答案 0 :(得分:2)

我们可以做到没有任何循环。只需对第一个数据集“ df”和“ f_freq”中的列子集进行left_join(无需在新数据集中创建“ F \ d +”列)。使用spread从“长”变形为“宽”

library(tidyverse)
left_join(df, f_freq[1:2]) %>%             
         spread(Feature, Freq, fill = 0)
#  PID Level F1 F2 F3
#1   1   low  0  2  1
#2   2   mid  3  1  2
#3   3  high  4  0  3

如果我们仅需要为'F'列提供二进制输出,请将'Freq'更改为1并执行spread

left_join(df, f_freq[1:2]) %>%    
     mutate(Freq = 1) %>%
     spread(Feature, Freq, fill = 0)