klonowsk

klonowsk

Having trouble splitting rows using Explorer.DataFrame

Hi,

I’m having trouble figuring out how to take a dataframe, split one of the text cells based on a function, and create new rows with the results, with all other column data duplicated for each row.

I just can’t figure out how to convert the list of text fragments into something that can be expanded into additional rows.

My (naïve) stab at it looks as follows for now:

require Explorer.DataFrame, as: DF
require Explorer.Series, as: S

defmodule MyDF do
  def apply(df, column, new_column, func) do
    series = DF.pull(df, column)
    list = S.to_list(series)

    new_series =
      list
      |> Enum.map(&func.(&1))
      |> S.from_list()

    DF.put(df, new_column, new_series)
  end
end

df = DF.new(
  class: [1, 2, 1, 3],
  text: ["AAA, BBB", "CCC, DDD", "EEE", "FFF, GGG, HHH"]
)

df
|> MyDF.apply("text", "new_text", &String.split(&1, ","))

Resulting in:

#Explorer.DataFrame<
Polars[4 x 3]
class integer [1, 2, 1, 3]
text string [“AAA, BBB”, “CCC, DDD”, “EEE”, “FFF, GGG, HHH”]
new_text list[string] [
[“AAA”, " BBB"],
[“CCC”, " DDD"],
[“EEE”],
[“FFF”, …]
]

But I would like that list of new_text to be spread accross multiple rows.

I’m coming from R+ and tidy/dplyr, where I would do something simple like:

df %>%
  dplyr::rowwise() %>%
  mutate(new_text = parse_text(text))

Thank you

Marked As Solved

billylanchantin

billylanchantin

Whoops! I forgot there was a bug with split which was just fixed last week:

I was on main locally so I didn’t see it. To workaround, you’ll need to do a pipeline like this:

df
|> DF.put("text", S.split(df["text"], ", "))
|> DF.explode("text")

(@bdarla’s approach works too.)

Or you can use main until the next release. Sorry about that!

Also Liked

billylanchantin

billylanchantin

Hi @klonowsk,

If I’ve followed what you’re trying to achieve, I think this works:

require Explorer.DataFrame, as: DF

df = DF.new(
  class: [1, 2, 1, 3],
  text: ["AAA, BBB", "CCC, DDD", "EEE", "FFF, GGG, HHH"]
)

df
|> DF.mutate(text: split(text, ", "))
|> DF.explode("text")
# #Explorer.DataFrame<
#   Polars[8 x 2]
#   class s64 [1, 1, 2, 2, 1, ...]
#   text string ["AAA", "BBB", "CCC", "DDD", "EEE", ...]
# >
bdarla

bdarla

Indeed, it seems that a previous cell in my Livebook allowed the code to run. Please, try the following:

Mix.install([
  {:axon, "~> 0.6"}, 
  {:nx, "~> 0.7"}, 
  {:explorer, "~> 0.8"}, 
  {:kino, "~> 0.12"}
])
require Explorer.DataFrame, as: DF
require Explorer.Series, as: S
text_list = ["AAA, BBB", "CCC, DDD", "EEE", "FFF, GGG, HHH"]
text = S.from_list(text_list)
df = DF.new(
class: [1, 2, 1, 3],
text: text_list
)
split_list = S.split(text, ", ")
df
|> DF.mutate(text: ^split_list)
|> DF.explode(:text)

Last Post!

klonowsk

klonowsk

Yes, all the above solutions work, and yes, I fell for the S.split() issue, however, sourcing from git:main results in far too many dependencies braking, so DF.put("text", S.split(df["text"], ", ")) works just fine for this toy example as well as for my needs as I have my own somewhat more complex text splitting function, which I just modified to return a series lists of the split texts to feed into DF.put(). The more relevant function is DF.explode(), which was missing from the version of the Explorer library I was using. So thank you!

Where Next?

Popular in Questions Top

rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" =&gt; #BSON.ObjectId&lt;58eb1a7a9ad169198c3dXXXX&gt;, "email" =&gt; ...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New

Other popular topics Top

jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 40042 209
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 44139 214
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

We're in Beta

About us Mission Statement