Python interpolate not working on rows - python

Related to Error in gapfilling by row in Pandas, I would like to interpolate instead of using fillna. Currently, I am doing this:
df.ix[:,'2015':'2100'].interpolate(axis = 1, method = 'linear')
However, this does not seem to replace the NaN's. Any suggestion?
--EDIT
This does not seem to work either:
df.apply(pandas.Series.interpolate, inplace = True)

This looks like a bug (I'm using Pandas 0.16.2 with Python 3.4.3).
Using a subset of your data:
>>>df.ix[:3, '2015':'2020']
2015 2016 2017 2018 2019 2020
0 0.001248 NaN NaN NaN NaN 0.001281
1 0.009669 NaN NaN NaN NaN 0.009963
2 0.020005 NaN NaN NaN NaN 0.020651
The linear interpolation works fine and returns a new dataframe.
>>> df.ix[:3, '2015':'2020'].interpolate(axis=1, method='linear')
2015 2016 2017 2018 2019 2020
0 0.001248 0.001255 0.001261 0.001268 0.001275 0.001281
1 0.009669 0.009728 0.009786 0.009845 0.009904 0.009963
2 0.020005 0.020134 0.020264 0.020393 0.020522 0.020651
3 0.025557 0.025687 0.025818 0.025949 0.026080 0.026211
The original is still untouched.
>>> df.ix[:4, '2015':'2020']
2015 2016 2017 2018 2019 2020
0 0.001248 NaN NaN NaN NaN 0.001281
1 0.009669 NaN NaN NaN NaN 0.009963
2 0.020005 NaN NaN NaN NaN 0.020651
3 0.025557 NaN NaN NaN NaN 0.026211
4 0.060077 NaN NaN NaN NaN 0.060909
So let's to to change it using the inplace=True parameter.
df.ix[:3, '2015':'2020'].interpolate(axis=1, method='linear', inplace=True)
>>> df.ix[:4, '2015':'2020']
2015 2016 2017 2018 2019 2020
0 0.001248 NaN NaN NaN NaN 0.001281
1 0.009669 NaN NaN NaN NaN 0.009963
2 0.020005 NaN NaN NaN NaN 0.020651
3 0.025557 NaN NaN NaN NaN 0.026211
4 0.060077 NaN NaN NaN NaN 0.06090
The changes didn't hold.

Related

Create empty square Dataframe from single column DataFrame

I have the following single column DataFrame:
df:
data = {'YEAR': [2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030],
}
df = pd.DataFrame(data)
df
How can I create an empty square Dataframe from df like the following DatFrame:
I´m kinda new to Python. I have tried converting the original Dataframme to list and the create a new dataframe from there without success. I also tried to do somekind concatenation but it does not work either.
I guess that its not as hard, but I dont know how to do that.
Try provide both index and columns as Year when creating the data frame:
df = pd.DataFrame([], index=data['YEAR'], columns=data['YEAR'])
df
2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030
2020 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2021 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2022 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2023 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2024 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2025 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2026 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2027 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2028 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2029 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2030 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
You can also use df.dot and replace:
df.set_index('YEAR').dot(df.set_index('YEAR').T).replace({0:''})
Use reindex:
df.reindex(columns=df.columns.union(df['YEAR']))
Output:
YEAR 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030
0 2020 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 2021 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 2022 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 2023 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 2024 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
5 2025 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
6 2026 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
7 2027 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
8 2028 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
9 2029 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
10 2030 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
You can do this by simply using pandas.DataFrame.loc :
df.loc[:, df.set_index("YEAR").index.tolist()]= np.NaN #or ""
# Output :
print(df)
YEAR 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030
0 2020 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 2021 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 2022 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 2023 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 2024 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
5 2025 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
6 2026 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
7 2027 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
8 2028 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
9 2029 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
10 2030 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

Replace dataframe values by NaN

I am working with a pandas dataframe of 15 rows and 8 columns, such a:
A B ... G H
0 0.158979 0.187282 ... 0.330566 0.458748
1 0.227254 0.273307 ... 0.489372 0.649698
2 0.308775 0.351285 ... 0.621399 0.833404
3 0.375850 0.444228 ... 0.759206 0.929980
4 0.431860 0.507906 ... 0.850741 1.038544
5 0.507219 0.596291 ... 0.980404 1.145819
6 0.570170 0.676551 ... 1.094201 1.282077
7 0.635122 0.750434 ... 1.155645 1.292930
8 0.704220 0.824748 ... 1.261516 1.395316
9 0.762619 0.887669 ... 1.337860 1.410864
10 0.824553 0.968889 ... 1.407665 1.437886
11 0.893413 1.045289 ... 1.519902 1.514017
12 0.946757 1.109964 ... 1.561611 1.478634
13 1.008294 1.174139 ... 1.596135 1.501220
14 1.053086 1.227203 ... 1.624630 1.503892
where columns from C to F have been omitted.
I would like to know how I can find the closest value to 1 for every column. Once this value is found I would like to replace the rest of the values in the columns by NaN, with the exception of the values corresponding to the previous and next row. Then obtaining a dataframe like that:
A B ... G H
0 NaN NaN ... NaN NaN
1 NaN NaN ... NaN NaN
2 NaN NaN ... NaN NaN
3 NaN NaN ... NaN 0.929980
4 NaN NaN ... 0.850741 1.038544
5 NaN NaN ... 0.980404 1.145819
6 NaN NaN ... 1.094201 NaN
7 NaN NaN ... NaN NaN
8 NaN NaN ... NaN NaN
9 NaN 0.887669 ... NaN NaN
10 NaN 0.968889 ... NaN NaN
11 NaN 1.045289 ... NaN NaN
12 0.946757 NaN ... NaN NaN
13 1.008294 NaN ... NaN NaN
14 1.053086 NaN ... NaN NaN
Does anyone has a sugestion for this?
Thanks in advance
you can use the fact that the closest to 1 is actually the min of the abs of df once remove 1. So check where the min is meet, use shift once with 1 and once with -1 to get the next and previous row. use this mask in where.
df_ = (df-1).abs()
df_ = df_.min() == df_
df_ = df_|df_.shift(1)|df_.shift(-1)
df_ = df.where(df_)
print(df_)
A B G H
0 NaN NaN NaN NaN
1 NaN NaN NaN NaN
2 NaN NaN NaN NaN
3 NaN NaN NaN 0.929980
4 NaN NaN 0.850741 1.038544
5 NaN NaN 0.980404 1.145819
6 NaN NaN 1.094201 NaN
7 NaN NaN NaN NaN
8 NaN NaN NaN NaN
9 NaN 0.887669 NaN NaN
10 NaN 0.968889 NaN NaN
11 NaN 1.045289 NaN NaN
12 0.946757 NaN NaN NaN
13 1.008294 NaN NaN NaN
14 1.053086 NaN NaN NaN

Converting pd.read_sql_query to pd.DataFrame converts strings to nan

When I try to take an SQL Query generated from a pd.read_sql_query to a dataframe using pd.DataFrame my string values get converted to nan.
I tried using dtypes to set the type of each column
SQL_Query = pd.read_sql_query('''SELECT [CircuitID], [Status],
[LatestJiraTicket], [MrcNew]
FROM CircuitInfoTable
WHERE ([Status] = 'Active')
OR ([Status] = 'Pending')
OR ([Status] = 'Planned')''', conn)
# print(SQL_Query)
cdf = pd.DataFrame(SQL_Query, columns=['CID', 'Status', 'JiraTicket', 'MrcNew'])
SQL Query output:
0 OH1004-01 ... NaN
1 OH1004-02 ... NaN
2 OH1005-01 ... NaN
3 OH1005-02 ... NaN
4 AL1001-01 ... NaN
5 AL1001-02 ... NaN
6 AL1007-01 ... NaN
7 AL1007-02 ... NaN
8 NC1001-01 ... NaN
9 NC1001-02 ... NaN
10 NC1001-03 ... NaN
11 NC1001-04 ... NaN
12 NC1001-05 ... NaN
13 NC1001-06 ... NaN
14 (ommited on purpose) ... 5200.0
15 MO001-02 ... NaN
16 OR020-01 ... 8000.0
17 MA004-01 ... 6500.0
18 MA004-02 ... 6500.0
19 OR004-01 ... 10500.0
20 (ommited on purpose) ... 3975.0
21 OR007-01 ... 2500.0
22 (ommited on purpose) ... 9200.0
23 (ommited on purpose) ... 15000.0
24 (ommited on purpose) ... 5750.0
25 CA1005-02 ... 47400.0
26 CA1005-03 ... 47400.0
27 CA1005-04 ... 47400.0
28 CA1005-05 ... 47400.0
29 CA1006-01 ... 0.0
DataFrame output:
CID Status JiraTicket MrcNew
0 nan Planned nan NaN
1 nan Planned nan NaN
2 nan Planned nan NaN
3 nan Planned nan NaN
4 nan Planned nan NaN
5 nan Planned nan NaN
6 nan Planned nan NaN
7 nan Planned nan NaN
8 nan Planned nan NaN
9 nan Planned nan NaN
10 nan Planned nan NaN
11 nan Planned nan NaN
12 nan Planned nan NaN
13 nan Planned nan NaN
14 nan Active nan 5200.0
15 nan Pending nan NaN
16 nan Pending nan 8000.0
17 nan Pending nan 6500.0
18 nan Pending nan 6500.0
19 nan Pending nan 10500.0
20 nan Active nan 3975.0
21 nan Pending nan 2500.0
22 nan Active nan 9200.0
23 nan Pending nan 15000.0
24 nan Active nan 5750.0
25 nan Pending nan 47400.0
26 nan Pending nan 47400.0
27 nan Pending nan 47400.0
28 nan Pending nan 47400.0
29 nan Pending nan 0.0
Basically, you are using columns argument incorrectly in pandas.DataFrame where that arugment specifies columns to select in resulting output (not to rename). From your query there is no CID or JiraTicket and hence they migrate with all missing values.
Possibly you intended to rename columns. Consider renaming in either SQL with column aliases or in pandas with rename or set_axis:
SELECT [CircuitID] AS [CID],
[Status],
[LatestJiraTicket] AS JiraTicket,
[MrcNew]
FROM CircuitInfoTable
WHERE ([Status] = 'Active')
OR ([Status] = 'Pending')
OR ([Status] = 'Planned')
Pandas
cdf = (pd.read_sql_query(...original query...)
.rename(columns={'CircuitID': 'CID', 'LatestJiraTicket': 'JiraTicket'})
)
cdf = (pd.read_sql_query(...original query...)
.set_axis(['CID', 'Status', 'JiraTicket', 'MrcNew'], axis='columns', inplace=False)
)

Fill in missing rows as NaN in python

I have a file that has daily precipitation data form 83 weather stations and 101 years per station. I want to determine number of NaN per year for each station.
As a shortened example lets assume I only have one stations and only care about 1 years of data, 2009.
If I have this:
station_id year month 1 2 3
210018 2009 1 5 6 8
210018 2009 2 NaN NaN 6
210018 2009 12 8 5 6
I want to get to this:
station_id year month 1 2 3
210018 2009 1 5 6 8
210018 2009 2 NaN NaN 6
210018 2009 3 NaN NaN NaN
210018 2009 4 NaN NaN NaN
210018 2009 5 NaN NaN NaN
210018 2009 6 NaN NaN NaN
210018 2009 7 NaN NaN NaN
210018 2009 8 NaN NaN NaN
210018 2009 9 NaN NaN NaN
210018 2009 10 NaN NaN NaN
210018 2009 11 NaN NaN NaN
210018 2009 12 8 5 6
So my station needs 12 rows for all 12 months and a year to go along with each one. Again I have 101 years in the real example.
I am trying to use this code:
df_indexed=df.set_index(['year'])
new_index=np.arange(1910,2011,1)
idx=pd.Index(new_index)
df2=df_indexed.reindex(idx, method=None)
but it returns a long error that ends with
ValueError: cannot reindex from a duplicate axis
I hope that makes sense.
What I'd probably do is create a target MultiIndex and then use that to index in. For example:
>>> target_ix = pd.MultiIndex.from_product([df.station_id.unique(),
np.arange(1910, 2011, 1), np.arange(1,13)],
names=["station_id", "year", "month"])
>>> df = df.set_index(["station_id", "year", "month"])
>>> new_df = df.loc[target_ix]
>>> new_df.tail(24)
1 2 3
station_id year month
210018 2009 1 5 6 8
2 NaN NaN 6
3 NaN NaN NaN
4 NaN NaN NaN
5 NaN NaN NaN
6 NaN NaN NaN
7 NaN NaN NaN
8 NaN NaN NaN
9 NaN NaN NaN
10 NaN NaN NaN
11 NaN NaN NaN
12 8 5 6
2010 1 NaN NaN NaN
2 NaN NaN NaN
3 NaN NaN NaN
4 NaN NaN NaN
5 NaN NaN NaN
6 NaN NaN NaN
7 NaN NaN NaN
8 NaN NaN NaN
9 NaN NaN NaN
10 NaN NaN NaN
11 NaN NaN NaN
12 NaN NaN NaN
You can .reset_index() at this point if you prefer.
[edit]
THIS IS NOT A PANDAS ANSWER: question was not tagged pandas when I started answering, I will let it here because it can benefit someone.
Suppose you organize your data using a dict where the keys are a tuple of (station_id, year, month) and the values are an array of your data points - you can use collections.defaultdict:
>>> data = defaultdict(lambda: [None, None, None])
>>> data[(210018, 2009, 3)]
[None, None, None]
You are probably reading from a file, I will not do all your homework for you - just give a few hints.
for line in file:
station_id, year, month, d1, d2, d3 = parse_line(line)
data[(station_id, year, month)] = [
None if d == 'NaN' else float(d) for d in (d1, d2, d3)
]
Writing the parse_line function is left as an exercise for the reader.

how to multiply multiple columns by a column in Pandas

I would like to have:
df[['income_1', 'income_2']] * df['mtaz_proportion']
return those columns multiplied by df['mtaz_proportion']
so that I can set
df[['mtaz_income_1', 'mtaz_income_2']] =
df[['income_1', 'income_2']] * df['mtaz_proportion']
but instead I get:
income_1 income_2 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
1 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
2 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
ect...
what simple thing am I missing?
Thank you!
use multiply method and set axis="index":
df[["A", "B"]].multiply(df["C"], axis="index")
Another way of writing the answer of HYRY:
df.loc[:,['A', 'B']] = df.loc[:,['A', 'B']].multiply(df.loc[:, 'C'], axis="index")
Convert both factors to numpy arrays using to_numpy:
df.loc[:, ['D', 'E']] = df[['A', 'B']].to_numpy() * df[['C']].to_numpy()

Categories