Kai
Kai

Reputation: 357

Python Pandas convert column data type

I know a question like this has been asked zillion types, but so far I have not been able to find an answer to this question.

I have joined two .csv files together with Pandas and now I would like to add some more columns to the new joined .csv file and the values calculate based on the already available data.

However, I keep getting this error:

"The truth value of a is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all()."

Now that obviously seems to be a problem with the data type of my column (which is all integers), but I have not found a (working) way to set that column as integers.

Here is my code:

import pandas

def nscap(ns):
    if ns <= 13:
        x = ns
    elif ns > 13:
        x = 13
    return x

df_1 = pandas.read_csv("a.csv", sep=';', names=["DWD_ID", "NS"], header=0)
df_2 = pandas.read_csv("b.csv", sep=';', names=["VEG", "DWD_ID"], header=0)
df_joined = pandas.merge(df_1, df_2, on="DWD_ID")
df_joined["NS_Cap"] = nscap(df_joined["NS"])

If i set

df_joined["NS_Cap"] = nscap(20)

the code works fine

I have tried functions like .astype(int) or .to_numeric() but unless I had the syntax wrong, it didn't work for me.

Thanks in advance!

Upvotes: 1

Views: 340

Answers (2)

Ami Tavory
Ami Tavory

Reputation: 76297

(Your code is missing a parenthesis at the end of nscap(df_joined["NS"].)

As @EdChum and @TheLaughingMan write, clip_upper is what you want here. This answer just addresses the direct reason for the error you're getting.

In the function

def nscap(ns):
    if ns <= 13:
        x = ns
    elif ns > 13:
        x = 13
    return x

effectively, ns <= 13 operations on a numpy.ndarray. When you compare such an array to a scalar, broadcasting takes place, and the result is an array where each element indicates whether it was true for it or not.

So

if ns <= 13:

translates to something like

if numpy.array([True, False, True, True]):

and it's impossible to understand whether this is true or not. That's the error you're getting: you need to specify whether you mean if all entries are true, if some entry is true, and so on.

Upvotes: 1

WGS
WGS

Reputation: 14169

As with @EdChum's comment, you need to use clip(upper=13) or clip_upper(13). One other option which can help you in the long run with instances like this is to use apply with a lambda function. This is a really nifty all-around method.

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randint(5,18,size=(5, 4)), columns=list('ABCD'))
nscap = lambda x: min(x, 13)

print df.head()
print '-' * 20

df['NSCAP'] = df['D'].apply(nscap)

print df.head()

Result:

enter image description here

Take note of the last 2 lines of the second dataframe.

Hope this helps.

Upvotes: 1

Related Questions