广播范围
Broadcasting ranges
我的数据框中有一个数组数组 - split.(df2.name)
:
> 392-element Array{Array{SubString{String},1},1}:
["chevrolet", "chevelle", "malibu"]
["buick", "skylark", "320"]
["plymouth", "satellite"]
["amc", "rebel", "sst"]
["ford", "torino"]
⋮
["ford", "mustang", "gl"]
["vw", "pickup"]
["dodge", "rampage"]
["ford", "ranger"]
["chevy", "s-10"]
我想 select 除了每个数组的第一个元素之外的所有元素并将它们连接在一起,以获得这些汽车的型号名称。
首先,我想做这样的事情:model = join.(split.(df2.name)[2:end], " ")
但不是删除每个数组的第一个元素,而是删除第一辆车(外部数组的第一个元素)。
所以我想通过在范围 model = join.(split.(df2.name).[2:end], " ")
之前放置一个点来将范围 [2:end]
广播到所有元素。但这似乎也不起作用,因为有语法错误:
syntax: missing last argument in "2:" range expression
那么在这种情况下广播范围的朱利安方法是什么?
一般来说,广播索引语法的工作原理是将其转换为 getindex
并广播:
model = join.(getindex.(split.(df2.name), Ref(2:10)), " ")
需要 Ref
才能将范围视为标量;您也可以改用 1 元组。
这是简单的部分。然而,这个技巧与 end
一起使用变得很难看,因为在括号之外它没有任何意义,这就是你得到错误的原因。解决问题的一种方法是将 end
替换为 lastindex
,但是您可能应该缓存数组计算:
model = let nameparts = split.(df2.name)
join.(getindex.(nameparts, Ref(2:lastindex(nameparts))), " ")
end
不过,这失去了广播融合的优势。
在这种特定情况下,您还可以使用 Iterators.rest
,因为我们知道 Array
迭代器的工作原理:
join.(Iterators.rest.(split.(df2.name), 2), " ")
但我认为最简单的版本只是一个理解:
model = [join(split(carname)[2:end]) for carname in df2.name]
(除非你对Iterators
非常熟悉。那我个人更喜欢前一个。)
在这里使用普通广播似乎有点棘手,因为正如您发现的那样,构建 2:end
范围会显式导致语法错误。我认为这是因为
这样的表达式
a[2:end]
经过特殊解析并降低为类似
的内容
a[2:lastindex(a)]
如 lastindex
的文档中所述。
然而,您可以使用像 Iterators.drop
这样的迭代器来遍历除第一个元素之外的所有元素,这是一个可以广播的操作:
julia> cars = [["chevrolet", "chevelle", "malibu"],
["buick", "skylark", "320"],
["plymouth", "satellite"],
["amc", "rebel", "sst"],
["ford", "torino"]];
julia> join.(Iterators.drop.(cars, 1), " ")
5-element Array{String,1}:
"chevelle malibu"
"skylark 320"
"satellite"
"rebel sst"
"torino"
但我认为在这种情况下,我可能会进行理解,我认为这会更具可读性:
julia> [join(car[2:end], " ") for car in cars]
5-element Array{String,1}:
"chevelle malibu"
"skylark 320"
"satellite"
"rebel sst"
"torino"
编辑: 回顾你的全球问题,看起来你首先 split
比你想要的更多,然后努力 join
恢复部分你一开始就不想分开。
因此您可能想利用 split
的 limit
关键字参数,这样一开始就不会拆分太多单词:
julia> cars2 = ["chevrolet chevelle malibu",
"buick skylark 320",
"plymouth satellite",
"amc rebel sst",
"ford torino"];
julia> split.(cars2, " ", limit=2)
5-element Array{Array{SubString{String},1},1}:
["chevrolet", "chevelle malibu"]
["buick", "skylark 320"]
["plymouth", "satellite"]
["amc", "rebel sst"]
["ford", "torino"]
julia> getindex.(split.(cars2, " ", limit=2), 2)
5-element Array{SubString{String},1}:
"chevelle malibu"
"skylark 320"
"satellite"
"rebel sst"
"torino"
最后一个示例还演示了如何通过显式 getindex(a, i)
函数调用广播索引语法,这是语法糖 a[i]
.
的简化形式
我的数据框中有一个数组数组 - split.(df2.name)
:
> 392-element Array{Array{SubString{String},1},1}:
["chevrolet", "chevelle", "malibu"]
["buick", "skylark", "320"]
["plymouth", "satellite"]
["amc", "rebel", "sst"]
["ford", "torino"]
⋮
["ford", "mustang", "gl"]
["vw", "pickup"]
["dodge", "rampage"]
["ford", "ranger"]
["chevy", "s-10"]
我想 select 除了每个数组的第一个元素之外的所有元素并将它们连接在一起,以获得这些汽车的型号名称。
首先,我想做这样的事情:model = join.(split.(df2.name)[2:end], " ")
但不是删除每个数组的第一个元素,而是删除第一辆车(外部数组的第一个元素)。
所以我想通过在范围 model = join.(split.(df2.name).[2:end], " ")
之前放置一个点来将范围 [2:end]
广播到所有元素。但这似乎也不起作用,因为有语法错误:
syntax: missing last argument in "2:" range expression
那么在这种情况下广播范围的朱利安方法是什么?
一般来说,广播索引语法的工作原理是将其转换为 getindex
并广播:
model = join.(getindex.(split.(df2.name), Ref(2:10)), " ")
需要 Ref
才能将范围视为标量;您也可以改用 1 元组。
这是简单的部分。然而,这个技巧与 end
一起使用变得很难看,因为在括号之外它没有任何意义,这就是你得到错误的原因。解决问题的一种方法是将 end
替换为 lastindex
,但是您可能应该缓存数组计算:
model = let nameparts = split.(df2.name)
join.(getindex.(nameparts, Ref(2:lastindex(nameparts))), " ")
end
不过,这失去了广播融合的优势。
在这种特定情况下,您还可以使用 Iterators.rest
,因为我们知道 Array
迭代器的工作原理:
join.(Iterators.rest.(split.(df2.name), 2), " ")
但我认为最简单的版本只是一个理解:
model = [join(split(carname)[2:end]) for carname in df2.name]
(除非你对Iterators
非常熟悉。那我个人更喜欢前一个。)
在这里使用普通广播似乎有点棘手,因为正如您发现的那样,构建 2:end
范围会显式导致语法错误。我认为这是因为
a[2:end]
经过特殊解析并降低为类似
的内容a[2:lastindex(a)]
如 lastindex
的文档中所述。
然而,您可以使用像 Iterators.drop
这样的迭代器来遍历除第一个元素之外的所有元素,这是一个可以广播的操作:
julia> cars = [["chevrolet", "chevelle", "malibu"],
["buick", "skylark", "320"],
["plymouth", "satellite"],
["amc", "rebel", "sst"],
["ford", "torino"]];
julia> join.(Iterators.drop.(cars, 1), " ")
5-element Array{String,1}:
"chevelle malibu"
"skylark 320"
"satellite"
"rebel sst"
"torino"
但我认为在这种情况下,我可能会进行理解,我认为这会更具可读性:
julia> [join(car[2:end], " ") for car in cars]
5-element Array{String,1}:
"chevelle malibu"
"skylark 320"
"satellite"
"rebel sst"
"torino"
编辑: 回顾你的全球问题,看起来你首先 split
比你想要的更多,然后努力 join
恢复部分你一开始就不想分开。
因此您可能想利用 split
的 limit
关键字参数,这样一开始就不会拆分太多单词:
julia> cars2 = ["chevrolet chevelle malibu",
"buick skylark 320",
"plymouth satellite",
"amc rebel sst",
"ford torino"];
julia> split.(cars2, " ", limit=2)
5-element Array{Array{SubString{String},1},1}:
["chevrolet", "chevelle malibu"]
["buick", "skylark 320"]
["plymouth", "satellite"]
["amc", "rebel sst"]
["ford", "torino"]
julia> getindex.(split.(cars2, " ", limit=2), 2)
5-element Array{SubString{String},1}:
"chevelle malibu"
"skylark 320"
"satellite"
"rebel sst"
"torino"
最后一个示例还演示了如何通过显式 getindex(a, i)
函数调用广播索引语法,这是语法糖 a[i]
.