【问题标题】:Fastest way to convert data frame to a list of comma-separated strings将数据框转换为逗号分隔字符串列表的最快方法
【发布时间】:2016-08-03 20:59:51
【问题描述】:

我有一个包含市镇名称和州名称的数据框。它看起来像这样:

 my.df <- structure(list(Location = c("Abatiá", "Adrianópolis", "Agudos do Sul", 
"Almirante Tamandaré", "Altamira do Paraná", "Altônia"), State = c("PR", 
"PR", "PR", "PR", "PR", "PR")), .Names = c("Location", "State"
), row.names = 0:5, class = "data.frame")

我需要做的是将此数据框转换为数组。预期的输出是这样的:

my.array$PR
Abatiá, PR
Adrianópolis, PR
Agudos do Sul, PR
...

my.array$RS
Vitória das Missões, RS
Westfalia, RS
Xangri-lá, RS
...

等等。

我怎样才能到达那里?

我的实际数据集大约有 10k 行,因此可能需要快速解决方案而不是易读性。谢谢!

【问题讨论】:

  • 你能粘贴dput(head(data)(和data你的data.frame)吗?
  • 是的,我编辑了 OP 以显示我的一些数据。
  • 我在数据中没有看到任何RS
  • 输出似乎不是数组而是字符列表(?),如果您不是在寻找数组结果,请编辑问题标题。
  • 10k 行对于 R 来说并没有那么大,所以考虑优先考虑可读性!

标签: arrays r performance dataframe type-conversion


【解决方案1】:

以下内容应该可以满足您的需求。

df = data.frame("location" = c("a", "b", "c", "d", "e", "f"), "state" = c("pr", "pr", "pr", "rs", "rs", "rs"), stringsAsFactors=F)
my.array = lapply(unique(df$state), function(x) paste(df$location[df$state == x], df$state[df$state == x], sep=", "))
names(my.array) = unique(df$state)
my.array$pr
# [1] "a, pr" "b, pr", "c, pr"

我简化了df 中的值,但要点保持不变。

【讨论】:

  • 这完全符合我的预期。谢谢!
【解决方案2】:

因为您想要一个类似列表的结果(即,您可以使用$ 进行索引),所以在State 上使用split。它自然会生成一个以States 为名称的列表

一个方法是先拆分

split_df <- split(my.df, my.df$State)
my.array <- sapply(names(split_df), function(name) 
                               paste(split_df[[name]][["Location"]],
                                     ", ", name, sep=""), 
                    USE.NAMES = TRUE)

第二种使用 split 的方式(在考虑了更多问题之后,似乎更优雅)是在位置之后直接拆分,状态对

# First, create a new vector (array) of location, state pairs
# use apply(X, 1, FUN) which works row-wise along X
# and for each row, paste it together
location_state <- apply(my.df,
                        1,
                        function(r) paste(r["Location"],
                                          r["State"],
                                          sep=', '))
#Second, split that vector, using State
split(location_state, my.df$State)

示例数据

states <- sapply(1:100, function(pass) paste0(sample(LETTERS, 2), collapse=""))
my.df <- data.frame(State=sample(states, 10000, replace=TRUE),
                 Location=sapply(1:1e4, function(pass) paste0(sample(letters, 5),
                                                         collapse="")), 
                    stringsAsFactors=FALSE)

【讨论】:

    【解决方案3】:

    使用 Reduce 怎么样?

    Reduce(function(...) paste(..., sep=", "), my.df)
    

    编辑:使用@thelatemail 建议更新基准测试

    #for your  benchmarking using 1 million rows
    library(rbenchmark)
    df <- data.frame(X=rnorm(1e6), Y=rnorm(1e6))
    benchmark(M1=Reduce(function(...) paste(..., sep=", "), df),
        M2=do.call(paste, c(df, sep=", ")))
    
    ##test replications elapsed relative user.self sys.self user.child sys.child
    ##1   M1           10   68.60    1.219     68.55     0.00         NA        NA
    ##2   M2           10   56.28    1.000     56.22     0.07         NA        NA
    

    do.call(paste, c(df, sep=", ")) 肯定更快!

    【讨论】:

    • 或再次do.call(paste, c(my.df,sep=", ") )。
    • 使用rnorm(1e6) 生成的df 不是解决这个问题的好基准:State 表示值很少,经常重复
    • 可能是states &lt;- sapply(1:100, function(pass) paste0(sample(LETTERS, 2), collapse="")) 然后是df &lt;- data.frame(State=sample(states, 10000, replace=TRUE), Loc=sapply(1:1e4, function(pass) paste0(sample(letters, 5), collapse="")))
    猜你喜欢
    • 2013-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-02
    • 2012-01-17
    • 2018-06-20
    相关资源
    最近更新 更多