Pandas DataFrame subtraction is getting an unexpected result. Concatenating instead? - pandas

I have two dataframes of the same size (510x6)
preds
0 1 2 3 4 5
0 2.610270 -4.083780 3.381037 4.174977 2.743785 -0.766932
1 0.049673 0.731330 1.656028 -0.427514 -0.803391 -0.656469
2 -3.579314 3.347611 2.891815 -1.772502 1.505312 -1.852362
3 -0.558046 -1.290783 2.351023 4.669028 3.096437 0.383327
4 -3.215028 0.616974 5.917364 5.275736 7.201042 -0.735897
... ... ... ... ... ... ...
505 -2.178958 3.918007 8.247562 -0.523363 2.936684 -3.153375
506 0.736896 -1.571704 0.831026 2.673974 2.259796 -0.815212
507 -2.687474 -1.268576 -0.603680 5.571290 -3.516223 0.752697
508 0.182165 0.904990 4.690155 6.320494 -2.326415 2.241589
509 -1.675801 -1.602143 7.066843 2.881135 -5.278826 1.831972
510 rows × 6 columns
outputStats
0 1 2 3 4 5
0 2.610270 -4.083780 3.381037 4.174977 2.743785 -0.766932
1 0.049673 0.731330 1.656028 -0.427514 -0.803391 -0.656469
2 -3.579314 3.347611 2.891815 -1.772502 1.505312 -1.852362
3 -0.558046 -1.290783 2.351023 4.669028 3.096437 0.383327
4 -3.215028 0.616974 5.917364 5.275736 7.201042 -0.735897
... ... ... ... ... ... ...
505 -2.178958 3.918007 8.247562 -0.523363 2.936684 -3.153375
506 0.736896 -1.571704 0.831026 2.673974 2.259796 -0.815212
507 -2.687474 -1.268576 -0.603680 5.571290 -3.516223 0.752697
508 0.182165 0.904990 4.690155 6.320494 -2.326415 2.241589
509 -1.675801 -1.602143 7.066843 2.881135 -5.278826 1.831972
510 rows × 6 columns
when I execute:
preds - outputStats
I expect a 510 x 6 dataframe with elementwise subtraction. Instead I get this:
0 1 2 3 4 5 0 1 2 3 4 5
0 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
2 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ...
505 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
506 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
507 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
508 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
509 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
I've tried dropping columns and the like, and that hasn't helped. I also get the same result with preds.subtract(outputStats). Any Ideas?

There are many ways that two different values can appear the same when displayed. One of the main ways is if they are different types, but corresponding values for those types. For instance, depending on how you're displaying them, the int 1 and the str '1' may not be easily distinguished. You can also have whitespace characters, such as '1' versus ' 1'.
If the problem is that one set is int while the other is str, you can solve the problem by converting them all to int or all to str. To do the former, do df.columns = [int(col) for col in df.columns]. To do the latter, df.columns = [str(col) for col in df.columns]. Converting to str is somewhat safer, as trying to convert to int can raise an error if the string isn't amenable to conversion (e.g. int('y') will raise an error), but int can be more usual as they have the numerical structure.
You asked in a comment about dropping columns. You can do this with drop and including axis=1 as a parameter to tell it to drop columns rather than rows, or you can use the del keyword. But changing the column names should remove the need to drop columns.

Related

pandas dataframe rebuild based on cells

after a lot of testing I have ended with this df:
Date 1 2 3 4 5 6 7 8 9 10
0 2019-01-02 59.92 NaN NaN NaN NaN NaN NaN NaN NaN NaN
0 2019-01-02 NaN 197.28 NaN NaN NaN NaN NaN NaN NaN NaN
0 2019-01-02 NaN NaN 96.59 NaN NaN NaN NaN NaN NaN NaN
0 2019-01-02 NaN NaN NaN 275.0 NaN NaN NaN NaN NaN NaN
0 2019-01-02 NaN NaN NaN NaN 209.94 NaN NaN NaN NaN NaN
0 2019-01-02 NaN NaN NaN NaN NaN 99.83 NaN NaN NaN NaN
0 2019-01-02 NaN NaN NaN NaN NaN NaN 257.89 NaN NaN NaN
0 2019-01-02 NaN NaN NaN NaN NaN NaN NaN 215.54 NaN NaN
0 2019-01-02 NaN NaN NaN NaN NaN NaN NaN NaN 187.06 NaN
0 2019-01-02 NaN NaN NaN NaN NaN NaN NaN NaN NaN 386.9
Would be nice any kind of trik to put all this values on the same row. Any idea?
Thanks!!
Try via groupby() and sum():
df=df.groupby('Date').sum()
output:
Date 1 2 3 4 5 6 7 8 9 10
2019-01-02 59.92 197.28 96.59 275.0 209.94 99.83 257.89 215.54 187.06 386.9
An option with groupby first in case this would need to be performed for multiple different types where sum may not behave as expected:
df = df.groupby('Date', as_index=False).first()
Date 1 2 3 4 5 6 7 8 9 10
2019-01-02 59.92 197.28 96.59 275.0 209.94 99.83 257.89 215.54 187.06 386.9

pandas pivot_table aggfunc wrong value

enter image description here
df_6m_sum = df_6m.pivot_table(index='ACC_NBR', columns='class', values='TRANS_CHARGE', aggfunc=np.sum)
df_6m_sum.head(10)
class bus enter busi campus online offline drink buy change finance
ACC_NBR
1300xxx0265 NaN NaN NaN NaN NaN NaN NaN 11700.0 NaN NaN
1300xxx0272 NaN NaN NaN NaN NaN NaN NaN 13500.0 NaN NaN
1300xxx0659 NaN NaN NaN NaN NaN NaN NaN 152300.0 NaN NaN
1300xxx0928 NaN NaN NaN NaN NaN NaN NaN 140000.0 NaN NaN
1300xxx1117 900.0 NaN NaN NaN 5500.0 2870.0 NaN 18020.0 10003.0 NaN
1300xxx1170 NaN NaN NaN NaN NaN NaN NaN 143000.0 NaN NaN
1300xxx1683 NaN NaN NaN NaN NaN NaN NaN 5200.0 NaN NaN
1300xxx1916 NaN NaN NaN NaN NaN NaN NaN NaN 10983.0 NaN
1300xxx2212 NaN NaN NaN NaN NaN NaN NaN 207030.0 NaN NaN
1300xxx2939 1800.0 NaN 5000.0 NaN NaN NaN NaN NaN NaN NaN
df_6m_sum.iloc[9]
class
交通 1800.0
娱乐 NaN
政企 5000.0
校园 NaN
线上缴费 NaN
线上购物 NaN
线上餐饮 NaN
线下购物 NaN
账户变动 NaN
金融 NaN
Name: 1300xxx2939, dtype: float64
df_6m_sum.loc['1300xxx2939']
class
交通 1400.0
娱乐 NaN
政企 7000.0
校园 NaN
线上缴费 NaN
线上购物 NaN
线上餐饮 NaN
线下购物 NaN
账户变动 NaN
金融 NaN
Name: 1300xxx2939, dtype: float64
I use pandas pivot_table to sum money, but the result is wrong (right value is 1400, 7000), why i use different select method get different value ,please help me ,thanks you
Problem solved, 1300xxx2939 have two type of data : str and int, both in acc_nbr column, so have two different value

In Python, how can I update multiple rows in a DataFrame with a Series?

I have a dataframe as below.
a b c d
2010-07-23 NaN NaN NaN NaN
2010-07-26 NaN NaN NaN NaN
2010-07-27 NaN NaN NaN NaN
2010-07-28 NaN NaN NaN NaN
2010-07-29 NaN NaN NaN NaN
2010-07-30 NaN NaN NaN NaN
2010-08-02 NaN NaN NaN NaN
2010-08-03 NaN NaN NaN NaN
2010-08-04 NaN NaN NaN NaN
2010-08-05 NaN NaN NaN NaN
And I have a series as below.
2010-07-23
a 1
b 2
c 3
d 4
I want to update the DataFrame with the series as below. How can I do?
a b c d
2010-07-23 NaN NaN NaN NaN
2010-07-26 1 2 3 4
2010-07-27 1 2 3 4
2010-07-28 1 2 3 4
2010-07-29 NaN NaN NaN NaN
2010-07-30 NaN NaN NaN NaN
2010-08-02 NaN NaN NaN NaN
2010-08-03 NaN NaN NaN NaN
2010-08-04 NaN NaN NaN NaN
2010-08-05 NaN NaN NaN NaN
Thank you very much for the help in advance.
If there is one column instead Series in s add DataFrame.squeeze with concat by length of date range, last pass to DataFrame.update:
r = pd.date_range('2010-07-26','2010-07-28')
df.update(pd.concat([s.squeeze()] * len(r), axis=1, keys=r).T)
print (df)
a b c d
2010-07-23 NaN NaN NaN NaN
2010-07-26 1.0 2.0 3.0 4.0
2010-07-27 1.0 2.0 3.0 4.0
2010-07-28 1.0 2.0 3.0 4.0
2010-07-29 NaN NaN NaN NaN
2010-07-30 NaN NaN NaN NaN
2010-08-02 NaN NaN NaN NaN
2010-08-03 NaN NaN NaN NaN
2010-08-04 NaN NaN NaN NaN
2010-08-05 NaN NaN NaN NaN
Or you can use np.broadcast_to for repeat Series:
r = pd.date_range('2010-07-26','2010-07-28')
df1 = pd.DataFrame(np.broadcast_to(s.squeeze().values, (len(r),len(s))),
index=r,
columns=s.index)
print (df1)
a b c d
2010-07-26 1 2 3 4
2010-07-27 1 2 3 4
2010-07-28 1 2 3 4
df.update(df1)
print (df)
a b c d
2010-07-23 NaN NaN NaN NaN
2010-07-26 1.0 2.0 3.0 4.0
2010-07-27 1.0 2.0 3.0 4.0
2010-07-28 1.0 2.0 3.0 4.0
2010-07-29 NaN NaN NaN NaN
2010-07-30 NaN NaN NaN NaN
2010-08-02 NaN NaN NaN NaN
2010-08-03 NaN NaN NaN NaN
2010-08-04 NaN NaN NaN NaN
2010-08-05 NaN NaN NaN NaN

Pandas access first column with duplicate column names

Looking for some help accessing the first empty df column that is also a duplicate name, by name.
Consider this dataframe
import pandas as pd
df = pd.DataFrame(columns=['A', 'B', 'C', 'C', 'C', 'C', 'D', 'E'], index=[0,1,2,3])
A B C C C C D E
0 NaN NaN NaN NaN NaN NaN NaN NaN
1 NaN NaN NaN NaN NaN NaN NaN NaN
2 NaN NaN NaN NaN NaN NaN NaN NaN
3 NaN NaN NaN NaN NaN NaN NaN NaN
then access a slice by indexer and column name
indexer = [1,3]
df.loc[indexer, 'C']
C C C C
1 NaN NaN NaN NaN
3 NaN NaN NaN NaN
I want to edit only the first instance of column C so that I get
A B C C C C D E
0 NaN NaN NaN NaN NaN NaN NaN NaN
1 NaN NaN 99 NaN NaN NaN NaN NaN
2 NaN NaN NaN NaN NaN NaN NaN NaN
3 NaN NaN 99 NaN NaN NaN NaN NaN
I tried df.loc[indexer, 'C'].iloc[:,0] = 99
But it did not set the values.
Thanks in advance for your replies and ideas.
IIUC:
indexer = [1, 3]
col = (df.columns == 'C').argmax()
df.iloc[indexer, col] = 99
df
A B C C C C D E
0 NaN NaN NaN NaN NaN NaN NaN NaN
1 NaN NaN 99 NaN NaN NaN NaN NaN
2 NaN NaN NaN NaN NaN NaN NaN NaN
3 NaN NaN 99 NaN NaN NaN NaN NaN
I would use index.get_loc to get the slice of integer location of columns C and passing its start to .iloc as follows:
indexer = [1, 3]
df.iloc[indexer, df.columns.get_loc('C').start] = 99
Or using np.nonzero
c_loc = np.nonzero(df.columns == 'C')[0]
df.iloc[indexer, c_loc[0]] = 99
Out[87]:
A B C C C C D E
0 NaN NaN NaN NaN NaN NaN NaN NaN
1 NaN NaN 99 NaN NaN NaN NaN NaN
2 NaN NaN NaN NaN NaN NaN NaN NaN
3 NaN NaN 99 NaN NaN NaN NaN NaN

High Dimensional Data with time series

I am trying to make a pandas dataframe to hold my experimental data. The data is described below:
I have ~300 individuals participating in an experiment made of ~200 trials, where each trial has a number of experimentally controlled parameters (~10 parameters). For every trial and every individual I have a timeseries of some measurement, which is 30 timepoints long.
What is the best way to structure this data into a dataframe? I will need to be able to do things like get the experimental values for every individual at a certain time during all the trials with certain parameters, or get average values over certain times and trials for an indivudal, etc. Basically I will need to be able to slice this data in most conceivable ways.
Thanks!
EDIT: If you want to look at how I have my data at the moment, scroll down to the last 3 cells in this notebook: https://drive.google.com/file/d/1UZG_S2fg4MzaED8cLwE-nKHG0SHqevUr/view?usp=sharing
The data variable has all the parameters for each trial, and the interp_traces variable is an array of the timeseries measurements for each timepoint, individual, and trial.
I'd like to put everything in one thing if possible. The multi-index looks promising.
In my opinion need MultiIndex.
Sample:
individuals = list('ABCD')
trials = list('ab')
par = list('xyz')
dates = pd.date_range('2018-01-01', periods=5)
n = ['ind','trials','pars']
mux = pd.MultiIndex.from_product([individuals, trials, par], names=n)
df = pd.DataFrame(index=mux, columns=dates)
print (df)
2018-01-01 2018-01-02 2018-01-03 2018-01-04 2018-01-05
ind trials pars
A a x NaN NaN NaN NaN NaN
y NaN NaN NaN NaN NaN
z NaN NaN NaN NaN NaN
b x NaN NaN NaN NaN NaN
y NaN NaN NaN NaN NaN
z NaN NaN NaN NaN NaN
B a x NaN NaN NaN NaN NaN
y NaN NaN NaN NaN NaN
z NaN NaN NaN NaN NaN
b x NaN NaN NaN NaN NaN
y NaN NaN NaN NaN NaN
z NaN NaN NaN NaN NaN
C a x NaN NaN NaN NaN NaN
y NaN NaN NaN NaN NaN
z NaN NaN NaN NaN NaN
b x NaN NaN NaN NaN NaN
y NaN NaN NaN NaN NaN
z NaN NaN NaN NaN NaN
D a x NaN NaN NaN NaN NaN
y NaN NaN NaN NaN NaN
z NaN NaN NaN NaN NaN
b x NaN NaN NaN NaN NaN
y NaN NaN NaN NaN NaN
z NaN NaN NaN NaN NaN