Rename column if its name matches to a name in given list

My Problem is :heavy_minus_sign: If name in names(dataframe) matches to a name in a given list then rename it to some other specified name.

names(dataframe)=["Date", "UT_start", "t-T0", "Filter", "Exp.", "OT", "Err.", "UL(3sig)", "Observ.", "GCN", "GRB"]
list=["Time", "Tmid", "T0", "t-T0", "t-to"] # rename  to "Time"

Please tell me how to make loop for it ?

Here you have it.

Please identify the following example in the documentation:

rename(df, Dict("i" => "A", "x" => "X"))

As you can see, you can generate a Dict from your list=["Time", "Tmid", "T0", "t-T0", "t-to"] and use the resulted Dict("Tmid" => "Time", "T0" => "Time" ... and so on.

To get your dict, you can use a dictionary comprehension approach like this:

oldtonew = Dict(old => "Time" for old in oldies)

You can use

for nm in names(dataframe)
    if nm in list 
        rename!(dataframe , Dict(nm => "Time"))
    end
end

As @algunion said when multiple column names repeated it will throw error and based on that you can use

i = 0 
for nm in names(dataframe)
    if nm in list 
        rename!(dataframe, nm => "Time"*string(i))
        i += 1
    end
end

which will give names Time0 , Time1 and so on .

You are welcome to Julia Discourse. :pray:

1 Like

nms=["Date", "UT_start", "Time", "t-T0", "Filter", "Exp.", "OT", "Err.", "UL(3sig)", "Observ.","t-to", "GCN","T0", "GRB"]
list=["Time", "Tmid", "T0", "t-T0", "t-to"] # rename  to "Time"

foreach(t-> !isnothing(t) ? nms[t]="Time" : t,   indexin(list,nms) )

julia> permutedims(nms)
1×14 Matrix{String}:
 "Date"  "UT_start"  "Time"  "t-T0"  "Filter"  "Exp."  "OT"  "Err."  "UL(3sig)"  "Observ."  "t-to"  "GCN"  "T0"  "GRB"

julia> foreach(t-> !isnothing(t) ? nms[t]="Time" : t,   indexin(list,nms) )

julia> permutedims(nms)
1×14 Matrix{String}:
 "Date"  "UT_start"  "Time"  "Time"  "Filter"  "Exp."  "OT"  "Err."  "UL(3sig)"  "Observ."  "Time"  "GCN"  "Time"  "GRB"

This is not working . :face_with_diagonal_mouth:

names(dataframe)=["Date", "UT_start", "t-T0", "Filter", "Exp.", "OT", "Err.", "UL(3sig)", "Observ.", "GCN", "GRB"]
list=["Time", "Tmid", "T0", "t-T0", "t-to"] # rename  to "Time"
oldtonew = Dict(old=> "Time" for old in list)
rename(dataframe,oldtonew)

And it is expected not to work - because the names to be changed need to also be in the column names of your data frame.

If you do intersect(names(dataframe), list), it will work:

names(dataframe)=["Date", "UT_start", "t-T0", "Filter", "Exp.", "OT", "Err.", "UL(3sig)", "Observ.", "GCN", "GRB"]
list=["Time", "Tmid", "T0", "t-T0", "t-to"] # rename  to "Time"
oldtonew = Dict(old=> "Time" for old in intersect(names(dataframe), list))
rename(dataframe,oldtonew)

Take a look at the documentation for DataFrames - you can use rename! if you want to do the changes in place (instead of getting a new DataFrame object).

Also - if multiple names will match, you’ll get multiple attempts to rename using the same name (Time): which will also produce an error. If multiple matches are found you might want to adapt the code to produce Time0, Time1 … and so on (or something to ensure you use unique names).

1 Like

What if i have many lists to intersect() with names(dataframe) and then assign them => unique names ?

The intersect function is pretty flexible:

manylists = [["a", "b", "c"], ["c", "d", "e"], ["r", "a", "c"]]
intersected = intersect(manylists...) # will output ["c"]

So you can intersect as many lists as you want (including the one containing your original data frame names).

Now, for generating unique names, you can try the following approach:

Dict(s => "Time$i" for (i, s) in enumerate(intersected))

In this way you will guarantee a mapping of old names to unique new names.

If you don’t want to only append an integer after “Time”, you might need another heuristic - but this is dependent on your context.

The code above is to help you get the gist of it.

Hope it helps.

No, You misunderstood .
I want to map every list to totally different name . For example:- i want map listb to Fersigan name.

listb=["mag", "Limit", "Magnitude","UL", "magn"]

map listc to raman etc.
What can i do instead of writing every time new code like given below:

namechange= Dict(name=> "Fersigan" for name in intersect(names(dataframe), listb))

To my mind, I covered this when expressing this:

If you want to do a different name mapping, you just need to encode it accordinlgy:

Dict(s => uppercasefirst(s) for (i, s) in enumerate(intersected))

The above mapping will rename "mag" to "Mag", "lag" to "Lag" and so on (also, if the index is no longer needed, you can drop the enumerate).

One more thing, if you want to apply that rule to all column names in your data frame, you don’t actually need to build that dictionary anymore.

Here we just pass the mapping function to the rename as follows:

rename(uppercasefirst, dataframe)

I am just showing here that rename has many helpful methods that you can use - this is one of them (and I am not saying this is the exact one you need - maybe you want to stick with the approach that was already showcased in the current thread).

No, You again misunderstood.
I don’t want to change first letter of name "mag" to "Mag", "lag" to "Lag" etc.
Please see my modified post 10 again.

At last i found good concise solution :laughing:

list=["Time", "Tmid", "T0", "t-T0", "t-to"] # rename  to "Time"
listb=["mag", "Limit", "Magnitude","OT", "magn"]
oldtonew = Dict(name=> "Time" for name in intersect(names(df), list)) 
otn=Dict(name=> "Mag" for name in intersect(names(df), listb))
merge!(oldtonew,otn)
rename!(df,oldtonew)

Great, a identical outcome with a diferent approach might be this:

renfun = let
    list = ["Time", "Tmid", "T0", "t-T0", "t-to"] # rename  to "Time"
    listb = ["mag", "Limit", "Magnitude", "OT", "magn"]
    function (name)
        name in list && return "Time"
        name in listb && return "Mag"
        return name
    end
end

rename!(renfun, df)

In both the solution you settled for and the function-based one, the assumption is that your data frame will not contain more than one column that matches values from list or listb (to keep the unique column condition).

1 Like

@algunion I want a function that can be used again and again. I have written below code but it is not working. What if i have 3 or more different lists.

function change()
    names(df)=["Date", "UT_start", "t-T0", "Filter", "Exp.", "OT", "Err", "UL(3sigma)", "Telescope", "GCN", "GRB"]
    name=names(df)
    for i in 1:length(name)
    @show name[i]
    i=+1
    list = ["Time", "Tmid", "T0", "t-T0", "t-to"] # rename  to "Time"
    listb = ["mag", "Limit", "Magnitude", "OT", "magn"]
    name[i] in list && return a=Dict("name"=>"Time")
    name[i] in listb && return b=Dict("name"=>"Mag")
    end
    return c=merge!(a,b)
end
change()
rename!(df,c)

All Julia functions can be used again and again.

“not working” can have multiple meanings:

  • it throws an error
  • it doesn’t throw errors, but it also doesn’t produce the intended effects

So, when saying something doesn’t work, you need to provide enough context so those willing to help can help (without doing guesswork).

The principle is to share a minimal working example (MWE): which means a code snippet that can be copy-pasted by those willing to help and that will reproduce the specific issue stated by you.

Now, from the thread context, I know that this is something related to renaming data frame columns. But given the code you shared and the ambiguous “not working” statement I can only speculate (and I don’t want to do that).

In conclusion:

  • please share a proper MWE
  • precisely state the issue you are experiencing
1 Like

I have to create a function change() that can change the column name if column name matches to any alternative given in list .

If i was able to write a MWE then why should i have asked you. :innocent:

function change()
    names(df)=["Date", "UT_start", "t-T0", "Filter", "Exp.", "OT", "Err", "UL(3sigma)", "Telescope", "GCN", "GRB"]
    name=names(df)
    list = ["time", "Tmid", "T0", "t-T0", "t-to"] # rename  to "Time"
    listb = ["mag", "Limit", "Magnitude", "OT", "magn"]
    for i in 1:length(name)
        if name[i] in list ; rename!(df,Dict("name[i]"=>"Time")); end
        if name[i] in listb ; rename!(df,Dict("name[i]"=>"Mag")); end
    	i=+1
    end
end

I understand - but I don’t see what I (or anyone wanting to help) can do here to help (besides actually writing the code for you - which is beyond the scope of this community platform).

If this is your reply I think you are missing the meaning of the MWE.

I quote myself:

The MWE doesn’t imply that you solve your problem and post the solution: it means to share a code snippet that we can run to reproduce your issue. I think the quote above correctly reflects this.

Now, you are free to formulate your posts as you see fit. However, if you want to get help, you need to be sure you convey enough information so others can provide valuable help: doing the work for (instead of) you is not actually helping (in the long run).

So it is not enough to just state what you want to achieve and expect others to deliver the code for you.

I am here to help (within the limits of my knowledge and experience) - but I don’t think the purpose of this community platform is to fulfill code requests.

Please also take a look at the following guidelines.

So, again:

  • please share a proper MWE
  • precisely state the issue you are experiencing
1 Like

This code is not changing t-T0 column name to Time and also column name OT to Mag . I have posted two MWE in last two posts. You can hint me resources that i can read.

Summary
using HTTP, CSV, DataFrames
function doanalysis()
    dfg=nothing
    for x in 31520
    print("\r peeking at GCN $x ")
        try
            url = "https://gcn.nasa.gov/circulars/$x.txt"
            resp = HTTP.get(url) 
            status=resp.status
            print(" ",status," "); 
            if status == 404 ; println("status=",status); continue; end          
            txt = String(resp.body)
            grb_rexp=r"GRB ?\d{6}([A-G]|(\.\d{2}))?"
				m=match(grb_rexp,txt)
				grb="nogrb"
                if occursin(grb_rexp,txt)
				    print(m.match)
					grb=m.match
			    end
            if occursin("IKI", txt)
                println(" IKI report")                
                he=first(findfirst(r"^(Date)|(UT start)|(T0+)"m,txt))
                lr=first(findnext(r"^\nThe |(Photometry)"m,txt,he))-1
                cltxt=replace(txt[he:lr], ","=>" ",r"(�+)"=>" " , "+/-"=>" ",">"=>" ","(mid)"=>" ",r"UT ?start"i=>"UT_start")
                df=CSV.read(IOBuffer(cltxt), DataFrame, skipto=3, delim=" ", ignorerepeated=true)
                df.GCN=[x for i in 1:nrow(df)]
                df.GRB=[m.match for i in 1:nrow(df)] 
				function change()
   				names(df)=["Date", "UT_start", "t-T0", "Filter", "Exp.", "OT", "Err", "UL(3sigma)", "Telescope", "GCN", "GRB"]
          		name=names(df)
   			    list = ["time", "Tmid", "T0", "t-T0", "t-to"] # rename  to "Time"
    			listb = ["mag", "Limit", "Magnitude", "OT", "magn"]
    			for i in 1:length(name)
        			if name[i] in list ; rename!(df,Dict("name[i]"=>"Time")); end
        			if name[i] in listb ; rename!(df,Dict("name[i]"=>"Mag")); end
    			i=+1
    			end
				end
				if isnothing(dfg) 
                    @show dfg=df
                else
                    @show dfg=vcat(dfg,df,cols=:union)
                end # if x is first
            end # if occursin
        catch e
            println("error ")                    
        end # trycatch
    end # for loop
end
doanalysis()

Yes - your code is not doing that.

Your code it is not changing any column name: you do not invoke any rename functions.

Why would you expect your code to change any column name?

Also, you are defining a function (change) inside a for loop (which should not be done). Anyway, you are not calling your function anywhere.

No, you didn’t. Your change function that you included in those posts cannot actually be run because it depends on some state that is not part of your function (e.g., df variable).

2 Likes

It is still giving error. I have invoked rename! function inside if conditional loop.

Summary
using HTTP, CSV, DataFrames
function doanalysis()
    dfg=nothing
	function change()
          		name=names(df)
   			    list = ["time", "Tmid", "T0", "t-T0", "t-to"] # rename  to "Time"
    			listb = ["mag", "Limit", "Magnitude", "OT", "magn"]
    			for i in 1:length(name)
        			if name[i] in list ;  rename!(df,Dict("name[i]"=>"Time")); end
        			if name[i] in listb ; rename!(df,Dict("name[i]"=>"Mag")); end
    			i=+1
    			end
	end
    for x in 31520
    print("\r peeking at GCN $x ")
        try
            url = "https://gcn.nasa.gov/circulars/$x.txt"
            resp = HTTP.get(url) 
            status=resp.status
            print(" ",status," "); 
            if status == 404 ; println("status=",status); continue; end          
            txt = String(resp.body)
            grb_rexp=r"GRB ?\d{6}([A-G]|(\.\d{2}))?"
				m=match(grb_rexp,txt)
				grb="nogrb"
                if occursin(grb_rexp,txt)
				    print(m.match)
					grb=m.match
			    end
            if occursin("IKI", txt)
                println(" IKI report")                
                he=first(findfirst(r"^(Date)|(UT start)|(T0+)"m,txt))
                lr=first(findnext(r"^\nThe |(Photometry)"m,txt,he))-1
                cltxt=replace(txt[he:lr], ","=>" ",r"(�+)"=>" " , "+/-"=>" ",">"=>" ","(mid)"=>" ",r"UT ?start"i=>"UT_start")
                df=CSV.read(IOBuffer(cltxt), DataFrame, skipto=3, delim=" ", ignorerepeated=true)
                df.GCN=[x for i in 1:nrow(df)]
                df.GRB=[m.match for i in 1:nrow(df)] 
				change()
				if isnothing(dfg) 
                     dfg=df
                else
                    @show dfg=vcat(dfg,df,cols=:union)
                end # if x is first
            end # if occursin
        catch e
            println("error ")                    
        end # trycatch
    end # for loop
end
doanalysis()

I am getting error in try catch block.
image