Когда Pandas по умолчанию транслирует серию и кадры данных? - PullRequest
0 голосов
/ 17 февраля 2019

Я столкнулся с чем-то любопытным (для меня), пытаясь ответить на этот вопрос .

Скажем, я хочу сравнить серию формы (10,) с df формы (10,10):

np.random.seed(0)
my_ser = pd.Series(np.random.randint(0, 100, size=10))
my_df = pd.DataFrame(np.random.randint(0, 100, size=100).reshape(10,10))
my_ser > 10 * my_df

дает, как и ожидалось, матрицу формы df (10,10).Сравнение представляется построчным.

Однако рассмотрим этот случай:

df = pd.DataFrame({'cell1':[0.006209, 0.344955, 0.004521, 0, 0.018931, 0.439725, 0.013195, 0.009045, 0, 0.02614, 0],
              'cell2':[0.048043, 0.001077, 0,0.010393, 0.031546, 0.287264, 0.016732, 0.030291, 0.016236, 0.310639,0], 
              'cell3':[0,0,0.020238, 0, 0.03811, 0.579348, 0.005906, 0,0,0.068352, 0.030165],
              'cell4':[0.016139, 0.009359, 0,0,0.025449, 0.47779, 0, 0.01282, 0.005107, 0.004846, 0],
              'cell5': [0,0,0,0.012075, 0.031668, 0.520258, 0,0,0,2.728218, 0.013418]})
i = 0
df.iloc[:,i].shape
>(11,)
(10 * df.drop(df.columns[i], axis=1)).shape
>(11,4)
(df.iloc[:,i] > (10 * df.drop(df.columns[i], axis=1))).shape
>(11,15)

Насколько я могу судить, здесь Панды транслируют Серию с помощью df.Почему это так?

Желаемое поведение можно получить с помощью:

(10 * df.drop(df.columns[i], axis=1)).lt(df.iloc[:,i], axis=0).shape
>(11,4)

pd.__version__
'0.24.0'

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

То, что происходит, - это панды, использующие внутреннее выравнивание данных.Панды почти всегда выравнивают данные по индексам, будь то индекс строки или заголовок столбца.Вот краткий пример:

s1 = pd.Series([1,2,3], index=['a','b','c'])
s2 = pd.Series([2,4,6], index=['a','b','c'])
s1 + s2
#Ouput as expected:
a    3
b    6
c    9
dtype: int64

Теперь давайте запустим пару других примеров с другим индексированием:

s2 = pd.Series([2,4,6], index=['a','a','c'])
s1 + s2
#Ouput
a    3.0
a    5.0
b    NaN
c    9.0
dtype: float64

Декартово произведение происходит с дублирующимися индексами, и сопоставление имеет значение NaN += NaN.

И, нет соответствующих индексов:

s2 = pd.Series([2,4,6], index=['e','f','g'])
s1 + s2
#Output
a   NaN
b   NaN
c   NaN
e   NaN
f   NaN
g   NaN
dtype: float64

Итак, в вашем первом примере вы создаете pd.Series и pd.DataFrame с индексами диапазона по умолчанию, которые совпадают, отсюда и сравнениепроисходит, как и ожидалось.Во втором примере вы сравниваете заголовки столбцов ['cell2', 'cell3', 'cell4', 'cell5'] с индексом диапазона по умолчанию, который возвращает все 15 столбцов, и при отсутствии соответствия всем значениям будет False, сравнение NaNвозвращает False.

0 голосов
/ 19 февраля 2019

Нижняя строка , Pandas сравнивает каждое значение ряда со столбцом с заголовком, который соответствует индексу значения.Индексы во втором примере - 0..10, а имена столбцов cell1..4, поэтому ни одно имя столбца не совпадает, и вы просто добавляете новые столбцы.По сути, это означает, что ряд обрабатывается как информационный фрейм с индексом в качестве заголовков столбцов.


На самом деле вы можете видеть часть того, что делает панда в первом примере, если вы делаете серию длиннее, чем количество столбцов.:

>>> my_ser = pd.Series(np.random.randint(0, 100, size=20))
>>> my_df
    0   1   2   3   4
0   9  10  27  45  71
1  39  61  85  97  44
2  34  34  88  33   5
3  36   0  75  34  69
4  53  80  62   8  61
5   1  81  35  91  40
6  36  48  25  67  35
7  30  29  33  18  17
8  93  84   2  69  12
9  44  66  91  85  39
>>> my_ser
0     92
1     36
2     25
3     32
4     42
5     14
6     86
7     28
8     20
9     82
10    68
11    22
12    99
13    83
14     7
15    72
16    61
17    13
18     5
19     0
dtype: int64
>>> my_ser>my_df
      0      1      2      3      4      5      6      7      8      9   \
0   True   True  False  False  False  False  False  False  False  False
1   True  False  False  False  False  False  False  False  False  False
2   True   True  False  False   True  False  False  False  False  False
3   True   True  False  False  False  False  False  False  False  False
4   True  False  False   True  False  False  False  False  False  False
5   True  False  False  False   True  False  False  False  False  False
6   True  False  False  False   True  False  False  False  False  False
7   True   True  False   True   True  False  False  False  False  False
8  False  False   True  False   True  False  False  False  False  False
9   True  False  False  False   True  False  False  False  False  False

      10     11     12     13     14     15     16     17     18     19
0  False  False  False  False  False  False  False  False  False  False
1  False  False  False  False  False  False  False  False  False  False
2  False  False  False  False  False  False  False  False  False  False
3  False  False  False  False  False  False  False  False  False  False
4  False  False  False  False  False  False  False  False  False  False
5  False  False  False  False  False  False  False  False  False  False
6  False  False  False  False  False  False  False  False  False  False
7  False  False  False  False  False  False  False  False  False  False
8  False  False  False  False  False  False  False  False  False  False
9  False  False  False  False  False  False  False  False  False  False

Обратите внимание, что происходит - 92 сравнивается с первым столбцом, поэтому вы получаете один False на 93. Затем 36 сравнивается со вторым столбцом и т. Д. Если ваша серия совпадает по длиневаше количество столбцов, то вы получите ожидаемое поведение.

Но что происходит, когда ваша серия длиннее?Что ж, вам нужно добавить новый фальшивый столбец во фрейм данных, чтобы продолжить сравнение.Чем он заполнен?Я не нашел никакой документации, но у меня сложилось впечатление, что она просто заполняет False, поскольку сравнивать не с чем.Следовательно, вы получаете дополнительные столбцы, соответствующие длине ряда, все False.

Но как насчет вашего примера.Вы не получаете 11 столбцов, но 4 + 11 = 15! Давайте сделаем еще один тест:

>>> my_df = pd.DataFrame(np.random.randint(0, 100, size=100).reshape(10,10),columns=[chr(i) for i in range(10)])
>>> my_ser = pd.Series(np.random.randint(0, 100, size=10))
>>> (my_df>my_ser).shape
(10, 20)

На этот раз мы получили сумму измерений, 10 + 10 = 20, в качестве суммывыходных столбцов!

Какая разница?Панды сравнивают каждый индекс серии с соответствующим заголовком столбца.В вашем первом примере индекс из заголовков my_ser и my_df совпал, поэтому он сравнил их.Если есть дополнительные столбцы - выше, что происходит.Если все столбцы имеют разные имена, чем индексы серии, тогда все столбцы являются дополнительными, и вы получите свой результат, и что происходит в моем примере, где заголовки теперь являются символами, а индексы целыми числами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...