sehHeiden

sehHeiden

I have a DataFrame Value columns and a Column with a start date (NaiveDateTime) and an end date (NaiveDateTime) at which the values where meassured. I would like to “unroll” the dateframe so that, I get a row for every date (day of the year), for every sample in the data frame.

I know, how I would do it in pandas (perhaps not the most elegant solution).
I would compute the day of the year (day) of the start and end dates, construct a list of every doy withing this range as a new column and than explode to return t 1st NF and that it is.

How would I do that with Explorer?

I started with:

filtered_polls = polls
|> DF.filter(start_date >= ^start_date)

polls_timeline = filtered_polls
|> DF.put("start_day", S.day_of_year(filtered_polls["start_date"]))
|> DF.put("end_day", S.day_of_year(filtered_polls["end_date"]))

polls_timeline
|> DF.put("date_range", polls_timeline["start_day"]..polls_timeline["end_day"])
|> DF.print()

Which is due to the range can not work on two series. But un two zipped lists.

dates = polls_timeline["start_day"]
 |> S.to_list()
 |> Enum.zip(S.to_list(polls_timeline["end_day"]))
 |> Enum.map(fn {start_date, end_date} -> start_date..end_date end)
 |> Enum.map(&Enum.to_list(&1))

 polls_timeline
 |> DF.put("dates", dates)
 |> DF.print()

Which does not work. Because I can not add a list as data type. Next I still would not know how to unroll.

Showing Posts 14 to 5

sehHeiden

sehHeiden OP

Thanks for you help. You completly deconstructed it computed the inner list and than made a new DataFrame.

I think, we don’t have to do everything, like others do, but it has to make sense within its inner logic.

billylanchantin

billylanchantin

Thank you! That makes it much easier to answer.

So I think @josevalim’s answer was what you want (for now, see below):

df = DF.new([
  %{start_day: 244, end_day: 248, fw: 15.0},
  %{start_day: 247, end_day: 249, fw: 16.0}
])

df
|> DF.to_rows()
|> Enum.with_index()
|> Enum.flat_map(fn {row, index} ->
  row["start_day"]..row["end_day"]
  |> Enum.map(&Map.merge(row, %{"day" => &1, "index" => index}))
end)
|> DF.new()
|> DF.arrange(index) # You can order by any column
|> DF.print(limit: :infinity)
# +---------------------------------------------------------+
# |        Explorer DataFrame: [rows: 8, columns: 5]        |
# +-----------+-----------+---------+-----------+-----------+
# |    day    |  end_day  |   fw    |   index   | start_day |
# | <integer> | <integer> | <float> | <integer> | <integer> |
# +===========+===========+=========+===========+===========+
# | 244       | 248       | 15.0    | 0         | 244       |
# +-----------+-----------+---------+-----------+-----------+
# | 245       | 248       | 15.0    | 0         | 244       |
# +-----------+-----------+---------+-----------+-----------+
# | 246       | 248       | 15.0    | 0         | 244       |
# +-----------+-----------+---------+-----------+-----------+
# | 247       | 248       | 15.0    | 0         | 244       |
# +-----------+-----------+---------+-----------+-----------+
# | 248       | 248       | 15.0    | 0         | 244       |
# +-----------+-----------+---------+-----------+-----------+
# | 247       | 249       | 16.0    | 1         | 247       |
# +-----------+-----------+---------+-----------+-----------+
# | 248       | 249       | 16.0    | 1         | 247       |
# +-----------+-----------+---------+-----------+-----------+
# | 249       | 249       | 16.0    | 1         | 247       |
# +-----------+-----------+---------+-----------+-----------+

Also, I don’t want to speak for the core team, but explode does appear to be on the roadmap:

https://github.com/elixir-explorer/explorer/issues/296

So if/when that functionality is added, you can do a nearly one-to-one translation of the Pandas code.

sehHeiden

sehHeiden OP

@billylanchantin I just checked Polars also can do that. Polars Explode

But it’s not in the explorer documentation, olso the types list and array…
Am I right?

sehHeiden

sehHeiden OP

@billylanchantin I did it in Python Pandas and ilustrate it with some images.
I start with a DataFrame with start and Enddates and some values:

Than I add a column (last column), that holds the days from start to end date:


You see the brackets. Which implies the list. Than I “explode” the DataFrame. So that from any value in the list, the other row values are copied and the row-exists n times.

The image shows that line zero exists now 5 times, as the list in column day is exploded.

Here is the python code:

from pandas import read_csv

data_df = read_csv("../doy_data.csv")
data_df["day"] = data_df.apply(lambda x: list(range(x["start_day"], x["end_day"]+1)), axis="columns")
data_df = data_df.explode("day")
data_df.to_csv("doy_data_unrolled.csv", index=False)

How would I reach the result in Explorer?

billylanchantin

billylanchantin

I’m taking some liberties to illustrate the idea.

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

data = [
  %{start_date: ~D[2023-01-01], end_date: ~D[2023-01-03], value: 1},
  %{start_date: ~D[2023-02-01], end_date: ~D[2023-02-03], value: 2}
]

df =
  data
  |> DF.new()
  |> DF.mutate(
    start_day: day_of_year(start_date),
    end_day: day_of_year(end_date)
  )

computed_values =
  df
  |> DF.to_rows()
  |> Enum.flat_map(fn row ->
    Enum.map(row["start_day"]..row["end_day"], fn day ->
      # Hold onto "start_day" so we group-then-sort by it later
      row |> Map.take(["start_day", "value"]) |> Map.put("day", day)
    end)
  end)
  # Do whatever computation you're trying to do here.
  |> Enum.map(fn %{"day" => day, "value" => value} = row ->
    Map.put(row, "value2", day + value)
  end)
  # Now we can group by "start_day", which makes n_rows match again.
  |> Enum.group_by(&(&1["start_day"]), &(&1["value2"]))
  |> Enum.sort()
  |> Enum.map(fn {_start_day, values} -> Enum.sum(values) end)

DF.put(df, :computed_values, computed_values)

A few points:

  1. The above is not optimal. I focused in individual steps to clarify the idea.
  2. I admit, I don’t quite know what unrolling the list accomplishes if you need to collapse it back down. Presumably, for most computations you could skip the unrolling and just operate on the dataframe directly.

If you show exactly what computation you’re trying to accomplish, I could say more. But the above is what I meant by “grouping/etc”.

sehHeiden

sehHeiden OP

@billylanchantin I musst be afk and try clear the problem from remote as good as I can.

What I meant is, the original DataFrame has about ten entries.
Than I take the dates, as start and End number and construct either a list of list, or what @josevalim proposed A flat_map which creates a flat list list of length 40 or so and than makes a Series out of it.
So the problems from my point of few are:
a) Putting a Series of length 40 into a DataFrame of Shape 10, n_cols is not possible?!
b) I don’t know to transform the DataFrame to a length shape of 40, n_cols and preserve the same row order as in the Series.
You talked about grouping. How would it help in this topic?

billylanchantin

billylanchantin

Hey @sehHeiden,

I wasn’t able to follow why @josevalim’s suggestion doesn’t work. You say:

I think you’ll need to do the grouping/etc. while it’s still a list. Then I think the lengths should match.

Also, if you’re trying to do interpolation with dates, this answer might help.

sehHeiden

sehHeiden OP

The closest I have seen is the pivot_longer function. But it’s works on existing columns that are combined into one column. But instead of columns I have a list of data (of variable length).
@josevalim I hope that makes clear, what I want. Do you know how to address it?

sehHeiden

sehHeiden OP

Okay, so something like pandas iterrows or apply. I assume that is not possible in Elixir to Enum.map over a Data Frame.

nseaSeb

nseaSeb

Yes, I’m not at all sure about this. The map_rows/2 function is not available in Elixir’s Explorer library. It seems to be a function of the df library in R.

However, you can get a similar effect by using Enum.map/2 to iterate over each row of the DataFrame, unless I’m mistaken?

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
peck
Hi everyone. My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
bradley
I really like the adapter patterns that ecto, nebulex, waffle, etc. use and would love find something similar for a key management servic...
New
unaware8150
Hello folks! So at work, we are seeing some situations where we have to define some “fixed” strings that are used across the codebase in...
New
Cxx-mlr
I’m working on a small exercise involving update_in/3, and I came up with this solution: data = %{ name: "Periodic Table", category:...
New
Alvinkariuki
How Can I Optimise Compile Time Dependencies I have been building an elixir application for about 2 years now. Many modules and files ha...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews