Using where and between:
df['Age'] = df.Age.where(df.Age.between(5, 100))
df
ID Age
0 1 NaN
1 2 NaN
2 3 25.0
3 4 NaN
4 5 45.0
Another option using .loc:
df.loc[df.Age.between(5, 100), 'Age'] = np.nan
Answer from BENY on Stack OverflowOf what I have understood, we are based on the values of xpos Type as External we need to update Length column in L as nan.
We are merging L and xpos on column N and then based on Type External in xpos we are updating Length of L by nan.
Code
L['Length'] = np.where(L.merge(xpos, on='N', how='inner').Type == 'External',np.nan,L.Length)
Output
N Length
0 1 NaN
1 2 NaN
2 3 400.0
3 4 200.0
Assuming the two data frames have the same length and are aligned on N:
mask = xpos['Type'] == 'External'
L.loc[mask, 'Length'] = np.nan
python - Replace a row in Pandas DataFrame with 'NaN' based on condition - Stack Overflow
python - Pandas: How to replace values to np.nan based on Condition for multiple columns - Stack Overflow
pandas - Python: how to replace NaN with conditions in a dataframe? - Stack Overflow
python - Replace NaN with Condition based on another column - Stack Overflow
I've been working on learning Python and for something to code, I picked some VBA that I had.
In VBA:
If Cells(I, "C").Value <> "" And Cells(I, "B").Value = "" Then
Cells(I, "B").Value = Cells(I, "C").Value
End IfIt simply checks if colC is not Null and colB is Null, then replaces colB with the value from colC.
I can read in the csv file, I was able to select and delete some rows I didn't want, but I can't seem to get the syntax right for this...
First of all get all indexes of values, that are below 20
idx = df[df.halon_gas >= 20].index
Then set the values for all columns and all columns which are below 200 to None
df.set_value(idx, df.columns , None)
This should write None/Nan in the rows with the value below 20
If you're fine with the rows being gone then I suggest you do this:
df.reset_index(level=0, inplace=True)
df = df[df.halon_gas <= 20]
df.set_index("index", inplace=True)
Whats happening here is the following:
- The Index gets reset so you have an extra Column with the Index Values pre Removal.
- Only the rows where df.halon_gas <= 20 are kept.
- The old Index values are set to be the Index for the DataFrame again.
First we create a dictionary from your two lists using zip
replace_dict = dict(zip(list1,list2))
then we loop over it to handle your assignments,
for k,v in replace_dict.items():
df.loc[df[k] == 0, v] = np.nan
print(df)
I A B C D E F
0 1 9 4 0 T F NaN
1 2 0 5 1 NaN X J
2 3 1 8 0 G G NaN
another method is to use np.where with your lists.
df[list2] = np.where(df[list1].eq(0), np.nan,df[list2])
print(df)
I A B C D E F
0 1 9 4 0 T F NaN
1 2 0 5 1 NaN X J
2 3 1 8 0 G G NaN
Let us do
df.loc[:,'D':].mask(df.loc[:,'A':'C'].eq(0).values)
D E F
0 T F NaN
1 NaN X J
2 G G NaN
df.loc[:,'D':]= df.loc[:,'D':].mask(df.loc[:,'A':'C'].eq(0).values)
you can use groupby to do this:
fill_value = df.groupby("node_i")["value_j"].mean().fillna(1.0)
df["w"] = fill_value.reindex(df["node_i"]).values
df["w"][df["value_j"].notnull()] = df["value_j"][df["value_j"].notnull()]
I Think you need fillna using once ffill and bfill and take average of it then fillna with 1 as:
df['w'] = ((df['value_j'].fillna(method='ffill')+df['value_j'].fillna(method='bfill'))/2).fillna(1).astype(int)
df
node_i node_j value_i value_j w
0 3 4 89 33.0 33
1 3 2 89 NaN 51
2 3 5 89 69.0 69
3 0 2 45 NaN 79
4 0 3 45 89.0 89
5 1 2 109 NaN 1
6 1 8 109 NaN 1
Updated Answer:
You can use groupby and transform to find mean then fillna with 1 and use np.where to fill the values of w as:
values = df.groupby('node_i')['value_j'].transform('mean').fillna(1)
df['w'] = np.where(df['value_j'].notnull(),df['value_j'],values).astype(int)
df
node_i node_j value_i value_j w
0 3 4 89 33.0 33
1 3 2 89 NaN 51
2 3 5 89 69.0 69
3 0 2 45 NaN 89
4 0 3 45 89.0 89
5 1 2 109 NaN 1
6 1 8 109 NaN 1
I understand from your question that you want to replace all the NaN values in Model with the Mode (Most Common Value) based on the values in Make. This can be done using the pandas library in Python. The code is as follows:
import pandas as pd
# Assuming you already have your dataset loaded into a DataFrame called 'df'
# Create a dictionary to store the mode for each 'Make'
make_mode_dict = {}
# Iterate through unique 'Make' values
for make in df['Make'].unique():
# Filter the DataFrame to rows with the current 'Make' value and 'Model' not NaN
make_subset = df.loc[(df['Make'] == make) & df['Model'].notna(), 'Model']
# Find the mode of 'Model' for the current 'Make'
mode_value = make_subset.mode().iloc[0]
# Store the mode in the dictionary with 'Make' as the key
make_mode_dict[make] = mode_value
# Function to replace NaN 'Model' values based on 'Make'
def replace_nan_model(row):
if pd.isna(row['Model']):
return make_mode_dict.get(row['Make'], None)
return row['Model']
# Apply the function to fill NaN values in the 'Model' column
df['Model'] = df.apply(replace_nan_model, axis=1)
In the code above, we first create a dictionary make_mode_dict to store the mode of the Model column for each unique Make value. Then, we iterate through each unique Make value, filter the DataFrame to rows with that specific Make value and non-NaN Model values, find the mode of the Model column for that Make, and store it in the dictionary.
After that, we define a function replace_nan_model that takes a row from the DataFrame as input. If the Model value in the row is NaN, it looks up the mode from the make_mode_dict based on the corresponding Make value and returns the mode value. If the Model value is not NaN, it returns the original value.
Finally, we apply the replace_nan_model function to the DataFrame using the apply method along axis=1, which means we apply the function row-wise to fill in the NaN values in the Model column based on the Make value.
After running this code, the Model column will hopefully have NaN values replaced with the mode for each Make value in the DataFrame. Hope this helps!
I would say that the easiest way to do this is by masking out the nan values and then replacing from a dictionary.
import pandas as pd
import numpy as np
# Creating example dataset
df = pd.DataFrame({"brand": ["Audi", np.nan], "model": ["a4", "ELR"]})
# The dictionary with model to brand
model_to_brand = {"ELR": "CADILLAC", "E-TRON": "Audi"}
mask = df["brand"].isna() # Creating a boolean mask
# Only replacing values of the cars selected by the mask
df.loc[mask, "brand"] = df.loc[mask, "model"].replace(model_to_brand)
# Printing out the modified dataframe
print(df)
Hope this helps!
You can use the new dtypes in pandas (since 1.0) that properly handle missing values:
df = pd.DataFrame({'a': [1, None, 3, 5], 'b': [2, 1, None, 2]})
df = df.convert_dtypes()
df['is_less'] = df['a'] < df['b']
print(df)
See https://pandas.pydata.org/pandas-docs/stable/user_guide/missing_data.html#missing-data-na
result:
a b is_less
0 1 2 True
1 <NA> 1 <NA>
2 3 <NA> <NA>
3 5 2 False
You can also use pd.array to directly create a dataframe with the new dtypes:
df = pd.DataFrame({
'a': pd.array([1, None, 3, 5]),
'b': pd.array([2, 1, None, 2]),
})
df['is_less'] = df['a'] < df['b']
print(df)
a b is_less
0 1 2 True
1 <NA> 1 <NA>
2 3 <NA> <NA>
3 5 2 False
Try rewriting your np.where statement:
df['is_less'] = np.where( (df['A'].isnull()) | (df['B'].isnull() ),np.nan, # check if A or B are np.nan
np.where(df['B'].ge(df['A']),'no','yes')) # check if B >= A
prints:
A B is_less
0 NaN 10.0 nan
1 10.0 NaN nan
2 1.0 5.0 no
3 5.0 1.0 yes
Greater than or equal
pandas.ge
fillna can take a series to replace NaN values with. Non-NaN values are left untouched.
Replace the month numbers with the values from your dictionary with map, then pass the result to fillna:
df["WL1"] = df.WL1.fillna(df.Month.map(dictionary["WL1"]))
You can convert your dictionary to pd.Series or pd.DataFrame, then merge it with the original dataset on Month column, then use fillna. Something like this:
import pandas as pd
import numpy as np
df = pd.DataFrame(dict(WL1=[np.nan, np.nan, 177.26], Month=[1, 2, 3]))
replacememnts = {
"WL1": {
1: 176.316,
2: 176.296,
3: 176.2825,
}
}
repl_df = pd.DataFrame(dict(repl=replacememnts["WL1"]))
df.merge(repl_df, left_on="Month", right_index=True).assign(
WL1=lambda x: x["WL1"].fillna(x["repl"])
).drop(columns=["repl"])
You could create a replacement_value: index_mask mapping using a dictionary and then iterate over it, like so:
>>> masks = {1: (df['B'] >= 10) & (df['B'] < 20) & df['C'].isnull(), 2: (df['B'] >= 20) & (df['B'] < 30) & df['C'].isnull(), 3: (df['B'] >= 30) & df['C'].isnull()}
>>> masks
{1: 0 False
1 False
2 True
3 False
dtype: bool, 2: 0 False
1 True
2 False
3 False
dtype: bool, 3: 0 False
1 False
2 False
3 False
dtype: bool}
>>> for replacement_value, mask in masks.items():
... df.loc[mask, 'C'] = replacement_value
...
>>> df
A B C
0 10 12 1.0
1 12 24 2.0
2 30 16 1.0
3 21 31 4.0
Note that I made the between conditions exclusive on the upper bound, i.e. to replace with 1 the value for df['B'] needs to be in the range [10, 20)]; to replace with 2 [20, 30), etc., because otherwise you have overlapping bounds.
I think you can try this :
import numpy as np
df['C'].loc[(df['B']<=10) & (df['B']>=1) & (df['C'].isnull())]=1
df['C'].loc[(df['B']<=20) & (df['B']>=11) & (df['C'].isnull())]=2
DataFrame.fillna() or Series.fillna() will do this for you.
Example:
In [7]: df
Out[7]:
0 1
0 NaN NaN
1 -0.494375 0.570994
2 NaN NaN
3 1.876360 -0.229738
4 NaN NaN
In [8]: df.fillna(0)
Out[8]:
0 1
0 0.000000 0.000000
1 -0.494375 0.570994
2 0.000000 0.000000
3 1.876360 -0.229738
4 0.000000 0.000000
To fill the NaNs in only one column, select just that column.
In [12]: df[1] = df[1].fillna(0)
In [13]: df
Out[13]:
0 1
0 NaN 0.000000
1 -0.494375 0.570994
2 NaN 0.000000
3 1.876360 -0.229738
4 NaN 0.000000
Or you can use the built in column-specific functionality:
df = df.fillna({1: 0})
It is not guaranteed that the slicing returns a view or a copy. You can do
df['column'] = df['column'].fillna(value)